using  System;
using  System.Diagnostics;
using  System.Web.Security;
using  System.Web;
using  System.Web.Services.Protocols;
using  System.Web.Configuration;
using  System.Security.Principal;
using  System.Security.Permissions;
using  System.Globalization;
using  System.Runtime.Serialization;
using  System.Collections;
using  System.Collections.Specialized;
using  System.Data;
using  System.Data.SqlClient;
using  System.Data.SqlTypes;
using  System.Security.Cryptography;
using  System.Text;
using  System.Text.RegularExpressions;
using  System.Configuration.Provider;
using  System.Configuration;
using  System.Web.DataAccess;
using  System.Web.Management;
using  System.Web.Util;

using  AddonNice;
using  AddonNice.Security;
using  AddonNice.Core;
using  AddonNice.Configuration;
using  AddonNice.Settings;
using  AddonNice.Helpers;
using  AddonNice.CRMWrapper;


namespace AddonNice.Authentication
{
	// Remove CAS from sample: [AspNetHostingPermission(SecurityAction.LinkDemand, Level=AspNetHostingPermissionLevel.Minimal)]
	// Remove CAS from sample: [AspNetHostingPermission(SecurityAction.InheritanceDemand, Level=AspNetHostingPermissionLevel.Minimal)]
	public class AddonNiceMembershipProvider : MembershipProvider
	{
	   
		// Provider ClassName
		public const string ProviderClassName   =   "AddonNiceMembershipProvider";

		#region Public properties

		public override bool    EnablePasswordRetrieval   { get { return _EnablePasswordRetrieval; } }

		public override bool    EnablePasswordReset       { get { return _EnablePasswordReset; } }

		public override bool    RequiresQuestionAndAnswer   { get { return _RequiresQuestionAndAnswer; } }

		public override bool    RequiresUniqueEmail         { get { return _RequiresUniqueEmail; } }

		public override MembershipPasswordFormat PasswordFormat { get { return _PasswordFormat; }}
		public override int MaxInvalidPasswordAttempts { get { return _MaxInvalidPasswordAttempts; } }

		public override int PasswordAttemptWindow { get { return _PasswordAttemptWindow; } }

		public override int MinRequiredPasswordLength
		{
			get { return _MinRequiredPasswordLength; }
		}

		public override int MinRequiredNonAlphanumericCharacters
		{
			get { return _MinRequiredNonalphanumericCharacters; }
		}

		public override string PasswordStrengthRegularExpression
		{
			get { return _PasswordStrengthRegularExpression; }
		}

		public override string ApplicationName
		{
			get 
			{ 
				string _AppName         =   string.Empty;
				PortalSettings p        =   (PortalSettings)HttpContext.Current.Items[StStr.strPortalSettings];
				if ( p != null )
					 _AppName           =   p.BaseAlias;
				else _AppName           =   _DefAppName;
				return _AppName; 
			}
			set
			{
				if (String.IsNullOrEmpty(value))
					throw new ArgumentNullException("value");

				if (value.Length > 256)
					throw new ProviderException( SR.GetString( SR.Provider_application_name_too_long ) );
				_DefAppName             =   value;
			}
		}
		
		public bool AutoCreateParentAccount
		{
			get
			{
				return _AutoCreateParentAccount;
			}
			set
			{
				_AutoCreateParentAccount = value;
			}
		}


		#endregion Public properties
		

		public int PortalID
		{
			get 
			{
				int _PortalID       =   _DefPortalID;
				PortalSettings p    =   (PortalSettings)HttpContext.Current.Items[StStr.strPortalSettings];
				if ( p != null )
					_PortalID       =   p.PortalID;
				return _PortalID; 
			}
			set
			{
				_DefPortalID            =  value;
			}
		}

		CRMWrapperBase Wrapper
		{
			get
			{
				return PortalSecurity.Wrapper;
			}
		}

		/// <summary>
		/// install a recent wrapper in dynEntity
		/// </summary>
		static public void ResetWrapper(DynEntity dyn)
		{
			dyn.SetWrapper(AddonNice.Security.PortalSecurity.Wrapper);
		}

		private string  _sqlConnectionString;
		private bool    _EnablePasswordRetrieval;
		private bool    _EnablePasswordReset;
		private bool    _RequiresQuestionAndAnswer;
		private string  _DefAppName                               =   string.Empty;
		private int     _DefPortalID                              =   0;
		private bool    _RequiresUniqueEmail;
		private int     _MaxInvalidPasswordAttempts;
		private int     _CommandTimeout;
		private int     _PasswordAttemptWindow;
		private int     _MinRequiredPasswordLength;
		private int     _MinRequiredNonalphanumericCharacters;
		private string  _PasswordStrengthRegularExpression;
		private int     _SchemaVersionCheck;
		bool _AutoCreateParentAccount                               =   true;
		private MembershipPasswordFormat _PasswordFormat;

		private const int      PASSWORD_SIZE  = 14;


		#region Initialize

		public override void Initialize(string name, NameValueCollection config)
		{
			if ( SecurityTraceSwitch.Sw.TraceVerbose )
				Trace.WriteLine( string.Format(CultureInfo.InvariantCulture,"[V]AddonNiceMembershipProvider Initialize BEG name: {0}",name),SecurityTraceSwitch.Sw.Info);
			// Remove CAS from sample: HttpRuntime.CheckAspNetHostingPermission (AspNetHostingPermissionLevel.Low, SR.Feature_not_supported_at_this_level);
			if (config == null)
				throw new ArgumentNullException("config");
			if (String.IsNullOrEmpty(name))
				name                                =   ProviderClassName;
			if (string.IsNullOrEmpty(config["description"])) 
			{
				config.Remove("description");
				config.Add("description", SR.GetString(SR.MembershipAddonNiceProvider_description));
			}
			base.Initialize(name, config);

			_SchemaVersionCheck                     =   0;

			_EnablePasswordRetrieval                =   SecUtility.GetBooleanValue(config, "enablePasswordRetrieval", false);
			_EnablePasswordRetrieval                =   SecUtility.GetBooleanValue(config, "enablePasswordRetrieval", false);
			_EnablePasswordReset                    =   SecUtility.GetBooleanValue(config, "enablePasswordReset", true);
			_RequiresQuestionAndAnswer              =   SecUtility.GetBooleanValue(config, "requiresQuestionAndAnswer", true);
			_RequiresUniqueEmail                    =   SecUtility.GetBooleanValue(config, "requiresUniqueEmail", true);
			_MaxInvalidPasswordAttempts             =   SecUtility.GetIntValue( config, "maxInvalidPasswordAttempts", 5, false, 0 );
			_PasswordAttemptWindow                  =   SecUtility.GetIntValue( config, "passwordAttemptWindow", 10, false, 0 );
			_MinRequiredPasswordLength              =   SecUtility.GetIntValue( config, "minRequiredPasswordLength", 7, false, 128 );
			_MinRequiredNonalphanumericCharacters   =   SecUtility.GetIntValue( config, "minRequiredNonalphanumericCharacters", 1, true, 128 );
			_AutoCreateParentAccount                =   SecUtility.GetBooleanValue(config, "autoCreateParentAccount", true);
			_PasswordStrengthRegularExpression      =   config["passwordStrengthRegularExpression"];
			if( _PasswordStrengthRegularExpression != null )
			{
				_PasswordStrengthRegularExpression  =   _PasswordStrengthRegularExpression.Trim();
				if( _PasswordStrengthRegularExpression.Length != 0 )
				{
					try
					{
						Regex regex = new Regex( _PasswordStrengthRegularExpression );
					}
					catch( ArgumentException e )
					{
						throw new ProviderException( e.Message, e );
					}
				}
			}
			else
			{
				_PasswordStrengthRegularExpression  =   string.Empty;
			}
			if (_MinRequiredNonalphanumericCharacters > _MinRequiredPasswordLength)
				throw new HttpException(SR.GetString(SR.MinRequiredNonalphanumericCharacters_can_not_be_more_than_MinRequiredPasswordLength));

			_CommandTimeout                         =   SecUtility.GetIntValue( config, "commandTimeout", 30, true, 0 );
			_DefAppName                             =   config["applicationName"];
			if (string.IsNullOrEmpty(_DefAppName))
				_DefAppName                         =   SecUtility.GetDefaultAppName();
			if( _DefAppName.Length > 256 )
			{
				throw new ProviderException(SR.GetString(SR.Provider_application_name_too_long));
			}
			_DefPortalID                            =   SecUtility.GetIntValue( config, "portalID", 0, true, 0 );

			string strTemp                          =   config["passwordFormat"];
			if (strTemp == null)
				strTemp                             =   "Hashed";

			switch(strTemp)
			{
			case "Clear":
				_PasswordFormat                     =   MembershipPasswordFormat.Clear;
				break;
			case "Encrypted":
				_PasswordFormat                     =   MembershipPasswordFormat.Encrypted;
				break;
			case "Hashed":
				_PasswordFormat                     =   MembershipPasswordFormat.Hashed;
				break;
			default:
				throw new ProviderException(SR.GetString(SR.Provider_bad_password_format));
			}

			if (PasswordFormat == MembershipPasswordFormat.Hashed && EnablePasswordRetrieval)
				throw new ProviderException(SR.GetString(SR.Provider_can_not_retrieve_hashed_password));
			//if (_PasswordFormat == MembershipPasswordFormat.Encrypted && MachineKeySection.IsDecryptionKeyAutogenerated)
			//    throw new ProviderException(SR.GetString(SR.Can_not_use_encrypted_passwords_with_autogen_keys));

			string temp                             =   config["connectionStringName"];
			if (temp == null || temp.Length < 1)
				throw new ProviderException(SR.GetString(SR.Connection_name_not_specified));
			_sqlConnectionString                    =   SqlConnectionHelper.GetConnectionString(temp, true, true);
			if (_sqlConnectionString == null || _sqlConnectionString.Length < 1) {
				throw new ProviderException(SR.GetString(SR.Connection_string_not_found, temp));
			}

			config.Remove("connectionStringName");
			config.Remove("enablePasswordRetrieval");
			config.Remove("enablePasswordReset");
			config.Remove("requiresQuestionAndAnswer");
			config.Remove("applicationName");
			config.Remove("requiresUniqueEmail");
			config.Remove("maxInvalidPasswordAttempts");
			config.Remove("passwordAttemptWindow");
			config.Remove("commandTimeout");
			config.Remove("passwordFormat");
			config.Remove("name");
			config.Remove("minRequiredPasswordLength");
			config.Remove("minRequiredNonalphanumericCharacters");
			config.Remove("passwordStrengthRegularExpression");
			config.Remove("autoCreateParentAccount");

			if ( SecurityTraceSwitch.Sw.TraceVerbose )
				Trace.WriteLine( string.Format(CultureInfo.InvariantCulture,"[V]AddonNiceMembershipProvider Initialize config.Count : {0}",config.Count ),SecurityTraceSwitch.Sw.Info);
			if (config.Count > 0) 
			{
				string attribUnrecognized = config.GetKey(0);
				if (!String.IsNullOrEmpty(attribUnrecognized))
					throw new ProviderException(SR.GetString(SR.Provider_unrecognized_attribute, attribUnrecognized));
			}
			if ( SecurityTraceSwitch.Sw.TraceVerbose )
				Trace.WriteLine( string.Format(CultureInfo.InvariantCulture,"[V]AddonNiceMembershipProvider Initialize END name: {0}",name),SecurityTraceSwitch.Sw.Info);
		}
		#endregion Initialize

		private int CommandTimeout
		{
			get{ return _CommandTimeout; }
		}


		#region CRM Access

		/// Request CRM server to extract the Guid from CRM using name and typecode
		/// </summary>
		private CrmCustomerId GetCustomerFromCRM(string username,int typeCode)
		{
			if ( SecurityTraceSwitch.Sw.TraceVerbose )
				Trace.WriteLine( string.Format(CultureInfo.InvariantCulture,"[V]AddonNiceMembershipProvider GetCustomerFromCRM begin portalID: {0}, typeCode: {1}, username: {2} ", 
					new object[] { PortalID,typeCode, username }),SecurityTraceSwitch.Sw.Info);
			Guid CrmCustomerID = Guid.Empty;
			try
			{
				InternalQueryExpression qe          =   new InternalQueryExpression();
				InternalColumnSet col	            =	new InternalColumnSet();
				InternalConditionExpression ce	    =   new InternalConditionExpression();
				switch (typeCode)
				{
					case (int)ADNTypeCodes.Account:
						qe.EntityName	        =   CrmStr.account;
						col.Attributes	        =   new string[] { CrmStr.accountid };
						ce.AttributeName        =   CrmStr.name;
						break;
					case (int)ADNTypeCodes.Lead:
						qe.EntityName	        =   CrmStr.lead;
						col.Attributes	        =   new string[] { CrmStr.leadid };
						ce.AttributeName        =   CrmStr.lastname;
						break;
					case (int)ADNTypeCodes.Contact:
						qe.EntityName	        =   CrmStr.contact;
						col.Attributes	        =   new string[] { CrmStr.contactid };
						ce.AttributeName        =   CrmStr.lastname;
						break;
					case (int)ADNTypeCodes.SystemUser:
						qe.EntityName	        =   CrmStr.systemuser;
						col.Attributes	        =   new string[] { CrmStr.systemuserid };
						ce.AttributeName        =   CrmStr.domainname;
						break;
					default:
						{
							string msg  =   string.Format("[E]AddonNiceMembershipProvider GetCustomerFromCRM unknown typeCode throwing exception portalID: {0}, typeCode: {1},username: {2} ", 
								new object[] { PortalID, typeCode, username });
							if ( SecurityTraceSwitch.Sw.TraceError )
								Trace.WriteLine(msg,SecurityTraceSwitch.Sw.Info);
							throw new Exception(msg);
						}
				}
				qe.ColumnSet			    =   col;
				ce.Operator				    =   InternalConditionOperator.Equal;
				ce.Values				    =   new object[] { username };

				qe.Criteria				    =   new InternalFilterExpression();
				qe.Criteria.FilterOperator  =   InternalLogicalOperator.And;
				qe.Criteria.Conditions	    =   new InternalConditionExpression[] { ce };

				InternalRetrieveMultipleRequest req  =   Wrapper.MakeRetrieveMultipleRequest(qe,true);
				InternalResponse retrieved  =   null;
				try 
				{
						retrieved           =   Wrapper.adminExecute(req);
				} 
				catch (Exception ex) 
				{
					if ( SecurityTraceSwitch.Sw.TraceError )
						Trace.WriteLine( string.Format(CultureInfo.InvariantCulture,"[E]AddonNiceMembershipProvider GetCustomerFromCRM ex: {0}", ex),SecurityTraceSwitch.Sw.Info);
					throw;
				}
				// Extract the DynamicEntity from the request.
				bool Ok                     =   Wrapper.Util.ExtractFirstCrmId(retrieved,typeCode,ref CrmCustomerID);

				if ( SecurityTraceSwitch.Sw.TraceVerbose )
					Trace.WriteLine( string.Format(CultureInfo.InvariantCulture,"[V]AddonNiceMembershipProvider GetCustomerFromCRM UserName: {0}, CrmCustomerId: '{1}', Ok: {2}", username, CrmCustomerID,Ok),SecurityTraceSwitch.Sw.Info);
				if ( Ok )
					return new CrmCustomerId(typeCode,CrmCustomerID);
			}
			catch (SoapException sx)
			{
				if ( SecurityTraceSwitch.Sw.TraceError )
					Trace.WriteLine( string.Format(CultureInfo.InvariantCulture,"[E]AddonNiceMembershipProvider GetCustomerFromCRM  ex: {0}-{1}", sx, sx.Detail.InnerText),SecurityTraceSwitch.Sw.Info);
				throw new CRMWrapperException("AddonNiceMembershipProvider GetCustomerFromCRM Sx", sx);
			}
			catch (CRMWrapperException)
			{
				throw;
			}
			catch (Exception ex)
			{
				if ( SecurityTraceSwitch.Sw.TraceError )
					Trace.WriteLine( string.Format(CultureInfo.InvariantCulture,"[E]AddonNiceMembershipProvider GetCustomerFromCRM ex: {0}", ex),SecurityTraceSwitch.Sw.Info);
				throw new CRMWrapperException("AddonNiceMembershipProvider GetCustomerFromCRM Sx", ex);
			}
			if ( SecurityTraceSwitch.Sw.TraceError )
				Trace.WriteLine( string.Format(CultureInfo.InvariantCulture,"[E]AddonNiceMembershipProvider GetCustomerFromCRM UserName: {0}, CrmCustomerId null", username),SecurityTraceSwitch.Sw.Info);
			return null;
		}

		/// <summary>
		/// Create a new user in CRM according to the typecode: lead, contact, account
		/// </summary>
		CrmCustomerId CreateInCRM(string username,int typeCode,Guid ownerGuid)
		{
			if ( SecurityTraceSwitch.Sw.TraceVerbose )
				Trace.WriteLine( string.Format(CultureInfo.InvariantCulture,"[V]AddonNiceMembershipProvider CreateInCRM BEG UserName: {0}, typeCode : {1}", username,typeCode),SecurityTraceSwitch.Sw.Info);
			Guid CrmCustomerID              =   Guid.Empty;
			try
			{
				DynEntity im				=   null;
				switch (typeCode)
				{
					case (int)ADNTypeCodes.Account:
						im					=   new ADNDynAccount(Wrapper, username);
						break;
					case (int)ADNTypeCodes.Lead:
						im					=   new ADNDynLead(Wrapper,string.Empty, username);
						break;
					case (int)ADNTypeCodes.Contact:
						im					=   new ADNDynContact(Wrapper,string.Empty,username);
						break;
				}
				im.SetOwnerFromUserId();
				im.ownerid                  =   ownerGuid;
				CrmCustomerID			    =   im.adminCreate();
			}
			catch (SoapException sx)
			{
				string msg                  =   string.Format("[E]AddonNiceMembershipProvider CreateInCRM  ex: {0}-{1}", sx, sx.Detail.InnerText);
				if ( SecurityTraceSwitch.Sw.TraceError )
					Trace.WriteLine( msg ,SecurityTraceSwitch.Sw.Info);
				throw new CRMWrapperException(msg, sx);
			}
			catch (CRMWrapperException)
			{
				throw;
			}
			catch (Exception ex)
			{
				string msg                  =   string.Format("[E]AddonNiceMembershipProvider CreateInCRM ex: {0}", ex);
				if ( SecurityTraceSwitch.Sw.TraceError )
					Trace.WriteLine( msg,SecurityTraceSwitch.Sw.Info);
				throw new CRMWrapperException(msg, ex);
			}
			if ( SecurityTraceSwitch.Sw.TraceVerbose )
				Trace.WriteLine( string.Format(CultureInfo.InvariantCulture,"[V]AddonNiceMembershipProvider CreateInCRM END Ok UserName: {0}, CrmCustomerId: {1}", username,CrmCustomerID),SecurityTraceSwitch.Sw.Info);
			return new CrmCustomerId(typeCode,CrmCustomerID);
		}
		
		/// <summary>
		/// Update the new customer created in CRM according to the typecode: lead, contact, account
		/// </summary>
		public void UpdateInCRM(AddonNiceMembershipUser user)
		{
			if ( SecurityTraceSwitch.Sw.TraceVerbose )
				Trace.WriteLine( string.Format(CultureInfo.InvariantCulture,"[V]AddonNiceMembershipProvider UpdateInCRM BEG UserName: {0}, typeCode : {1}", user.UserName,user.typeCode),SecurityTraceSwitch.Sw.Info);
			try
			{
				user.UpdateCrmData(AutoCreateParentAccount);
				}
			catch (SoapException sx)
			{
				string msg                  =   string.Format("[E]AddonNiceMembershipProvider UpdateInCRM  ex: {0}-{1}", sx, sx.Detail.InnerText);
				if ( SecurityTraceSwitch.Sw.TraceError )
					Trace.WriteLine( msg ,SecurityTraceSwitch.Sw.Info);
				throw new CRMWrapperException(msg, sx);
			}
			catch (CRMWrapperException)
			{
				throw;
			}
			catch (Exception ex)
			{
				string msg                  =   string.Format("[E]AddonNiceMembershipProvider UpdateInCRM ex: {0}", ex);
				if ( SecurityTraceSwitch.Sw.TraceError )
					Trace.WriteLine( msg,SecurityTraceSwitch.Sw.Info);
				throw new CRMWrapperException(msg, ex);
			}
			if ( SecurityTraceSwitch.Sw.TraceVerbose )
				Trace.WriteLine("[V]AddonNiceMembershipProvider UpdateInCRM END.",SecurityTraceSwitch.Sw.Info);
		}

		#endregion CRM Access

		#region Create User
		public bool TestAdmin(bool create)
		{
			if ( SecurityTraceSwitch.Sw.TraceVerbose )
				Trace.WriteLine( string.Format(CultureInfo.InvariantCulture,"[V]AddonNiceMembershipProvider TestAdmin create: {0}", create),SecurityTraceSwitch.Sw.Info);
			bool ret        =   false;
			string username =   Config.CRMServiceAccount;
			try
			{
				if ((Membership.GetUser(username) == null) && create)
				{
					if ( SecurityTraceSwitch.Sw.TraceVerbose )
						Trace.WriteLine( string.Format(CultureInfo.InvariantCulture,"[V]AddonNiceMembershipProvider TestAdmin creating username: {0}", username),SecurityTraceSwitch.Sw.Info);
					CreateAdmin();
				}
				ret         =   true;
			}
			catch(Exception ex) 
			{
				if ( SecurityTraceSwitch.Sw.TraceError )
					Trace.WriteLine( string.Format(CultureInfo.InvariantCulture,"[E]AddonNiceMembershipProvider TestAdmin username: {0}, ex: {1}", PortalID,ex),SecurityTraceSwitch.Sw.Info);
				ret         =   false;
			}
			return ret;
		}

		public MembershipUser CreateAdmin()
		{
			if ( SecurityTraceSwitch.Sw.TraceVerbose )
				Trace.WriteLine("[V]AddonNiceMembershipProvider CreateAdmin BEG",SecurityTraceSwitch.Sw.Info);
			string password                         =   Config.CRMServicePassword;
			HttpContext context                     =   HttpContext.Current;
			context.Items["CrmTypeCode"]            =   (int)ADNTypeCodes.Contact;
			context.Items["CrmImpersonateId"]       =   Wrapper.adminUserId;
			context.Items["CrmImpersonateDomain"]   =   Config.CRMServiceDomain;
			context.Items["CrmImpersonateLogin"]    =   Config.CRMServiceAccount;
			context.Items["CrmImpersonatePwd"]      =   password;
			context.Items["CrmIsCrmUser"]           =   true;
			try
			{
				ADNDynSystemUser sysAdmin           =   DynEntity.GetFromCache<ADNDynSystemUser>(CrmStr.systemuser,Wrapper,new ResetWrapperHandler(ResetWrapper),Wrapper.adminUserId);
				string username                     =   sysAdmin.domainname;
				string email                        =   sysAdmin.internalemailaddress;
				string passwordQuestion             =   "Key word";
				const string pwdadmin               =   "ecinnodda_nimda";
				string passwordAnswer               =   pwdadmin;
				bool isApproved                     =   true;
				object providerUserKey              =   null;
				MembershipCreateStatus status;
				MembershipUser Admin                =   CreateUser(username, password, email, passwordQuestion, passwordAnswer, 
																									isApproved, providerUserKey, out status);
				if (SecurityTraceSwitch.Sw.TraceVerbose)
					Trace.WriteLine( string.Format(CultureInfo.InvariantCulture,"[V]AddonNiceMembershipProvider CreateAdmin END user: {0}, status: {1}", username,status), SecurityTraceSwitch.Sw.Info);
				return Admin;
			}
			catch (Exception ex)
			{
				if (SecurityTraceSwitch.Sw.TraceError)
					Trace.WriteLine( string.Format(CultureInfo.InvariantCulture,"[E]AddonNiceMembershipProvider CreateAdmin portalID: {0}, ex: {1}", PortalID, ex), SecurityTraceSwitch.Sw.Info);
				throw;
			}
			finally
			{
				context.Items.Remove("CrmTypeCode");
				context.Items.Remove("CrmImpersonateId");
				context.Items.Remove("CrmImpersonateDomain");
				context.Items.Remove("CrmImpersonateLogin");
				context.Items.Remove("CrmImpersonatePwd");
				context.Items.Remove("CrmIsCrmUser");
			}
		}

		/// <summary>
		/// Initialy we have no pwd for this domain account, so we impersonate CRM on DefaultAccount, later, if user changes its pwd, 
		/// he will have to enter its real domain pwd and Membership pwd will be set on same value
		/// </summary>
		public MembershipUser CreateFromCrmUser(ADNDynSystemUser sysUser)
		{
			if (SecurityTraceSwitch.Sw.TraceVerbose)
				Trace.WriteLine( string.Format(CultureInfo.InvariantCulture,"[V]AddonNiceMembershipProvider CreateFromCrmUser BEG user: {0}.", sysUser.domainname), SecurityTraceSwitch.Sw.Info);
			string username                         =   sysUser.domainname;
			string password                         =   Config.CRMDefaultAccountPassword;
			HttpContext context                     =   HttpContext.Current;
			if ( Config.AuthenticationMode == AuthenticationMode.Forms )
				 context.Items["CrmTypeCode"]       =   (int)ADNTypeCodes.Contact;
			else context.Items["CrmTypeCode"]       =   (int)ADNTypeCodes.SystemUser;
			string domainName                       =   string.Format("{0}\\{1}",Config.CRMDefaultAccountDomain,Config.CRMDefaultAccount);
			ADNDynSystemUser sysAdmin               =   Wrapper.Util.FindSystemUserByDomainName(domainName);
			if (sysAdmin == null)
			{
				string msg                          =   string.Format("[E]AddonNiceMembershipProvider CreateFromCrmUser unable to find CrmDafaultAccount portalID: {0}, domaineName: {1}", PortalID, domainName);
				if (SecurityTraceSwitch.Sw.TraceError)
					Trace.WriteLine(msg, SecurityTraceSwitch.Sw.Info);
				return null;
			}
			context.Items["CrmImpersonateId"]       =   sysAdmin.systemuserid;
			context.Items["CrmImpersonateDomain"]   =   Config.CRMDefaultAccountDomain;
			context.Items["CrmImpersonateLogin"]    =   Config.CRMDefaultAccount;
			context.Items["CrmImpersonatePwd"]      =   password;
			context.Items["CrmIsCrmUser"]           =   true;
			try
			{
				string email                        =   sysUser.internalemailaddress;
				if ( string.IsNullOrEmpty(email) )
				{
					string domain                   =   Config.CRMDefaultAccountDomain;
					if ( domain.IndexOf('.') == -1 )
						domain                      =   domain+".local";
					if ( string.IsNullOrEmpty(sysUser.firstname) )
						 email                      =   string.Format("{0}@{1}",sysUser.lastname,domain);
					else email                      =   string.Format("{0}.{1}@{2}",sysUser.firstname,sysUser.lastname,domain);
					email                           =   email.Replace(" ",string.Empty);
					if (SecurityTraceSwitch.Sw.TraceVerbose)
						Trace.WriteLine( string.Format(CultureInfo.InvariantCulture,"[V]AddonNiceMembershipProvider CreateFromCrmUser email created: {0}.", email), SecurityTraceSwitch.Sw.Info);
				}
				string passwordQuestion             =   "Key word";
				string passwordAnswer               =   "maeteriw";
				bool isApproved                     =   true;
				object providerUserKey              =   null;
				MembershipCreateStatus status;
				MembershipUser auser                =   CreateUser(username, password, email, passwordQuestion, passwordAnswer, 
																							isApproved, providerUserKey, out status);
				if ( status == MembershipCreateStatus.Success )
				{
					string fmt                      =   LocalizeHelper.Localize("MEMBERSHIP_NEW_ACCOUNT","New Addon Nice account created, please finalize it");
					ADNDynActivityTask task         =   new ADNDynActivityTask(Wrapper,fmt);
					StringBuilder sb                =   new StringBuilder();
					fmt                             =   LocalizeHelper.Localize("MEMBERSHIP_NEW_MSG1","Your login name is '{0}' and password is the default Addon Nice password set by your administrator.");
					sb.AppendFormat(fmt,username);
					fmt                             =   LocalizeHelper.Localize("MEMBERSHIP_NEW_MSG2","You have to change your Addon Nice impersonation user and password to gain full access.");
					sb.AppendLine(fmt);
					fmt                             =   LocalizeHelper.Localize("MEMBERSHIP_NEW_MSG3","To do this, login AddonNice and change password.");
					sb.AppendLine(fmt);
					task.description                =   sb.ToString();
					task.ownerid                    =   sysUser.systemuserid;
					task.category                   =   "Addon Nice";
					task.prioritycode               =   2; // high
					task.adminCreate();
					if (SecurityTraceSwitch.Sw.TraceVerbose)
						Trace.WriteLine( string.Format(CultureInfo.InvariantCulture,"[V]AddonNiceMembershipProvider CreateFromCrmUser task created user: {0}", username), SecurityTraceSwitch.Sw.Info);
				}
				if (SecurityTraceSwitch.Sw.TraceVerbose)
					Trace.WriteLine( string.Format(CultureInfo.InvariantCulture,"[V]AddonNiceMembershipProvider CreateFromCrmUser user: {0}, status: {1}", username,status), SecurityTraceSwitch.Sw.Info);
				return auser;
			}
			catch (Exception ex)
			{
				if (SecurityTraceSwitch.Sw.TraceError)
					Trace.WriteLine( string.Format(CultureInfo.InvariantCulture,"[E]AddonNiceMembershipProvider CreateFromCrmUser portalID: {0}, ex: {1}", PortalID, ex), SecurityTraceSwitch.Sw.Info);
				throw;
			}
			finally
			{
				context.Items.Remove("CrmTypeCode");
				context.Items.Remove("CrmImpersonateId");
				context.Items.Remove("CrmImpersonateDomain");
				context.Items.Remove("CrmImpersonateLogin");
				context.Items.Remove("CrmImpersonatePwd");
				context.Items.Remove("CrmIsCrmUser");
			}
		}

		public override MembershipUser CreateUser( string username,
												   string password,
												   string email,
												   string passwordQuestion,
												   string passwordAnswer,
												   bool   isApproved,
												   object providerUserKey,
												   out    MembershipCreateStatus status )
		{
			if ( SecurityTraceSwitch.Sw.TraceVerbose )
				Trace.WriteLine( string.Format(CultureInfo.InvariantCulture,"[V]AddonNiceMembershipProvider CreateUser BEG portalID: {0}, username: {1}, password: {2}, passwordQuestion: {3},passwordAnswer: {4}, isApproved: {5}, providerUserKey: {6}",
					new object[]{PortalID, username,password,passwordQuestion,passwordAnswer,isApproved,providerUserKey}),SecurityTraceSwitch.Sw.Info);
			if( !SecUtility.ValidateParameter(ref password, true, true, false, 128))
			{
				status                  =   MembershipCreateStatus.InvalidPassword;
				return null;
			}

			string salt                 =   GenerateSalt();
			string pass                 =   EncodePassword(password, (int)_PasswordFormat, salt);
			if ( pass.Length > 128 )
			{
				status                  =   MembershipCreateStatus.InvalidPassword;
				return null;
			}

			string encodedPasswordAnswer;
			if( passwordAnswer != null )
			{
				passwordAnswer          =   passwordAnswer.Trim();
			}

			if (!string.IsNullOrEmpty(passwordAnswer)) 
			{
				if( passwordAnswer.Length > 128 )
				{
					status              =   MembershipCreateStatus.InvalidAnswer;
					return null;
				}
				encodedPasswordAnswer   =   EncodePassword(passwordAnswer.ToLower(CultureInfo.InvariantCulture), (int)_PasswordFormat, salt);
			}
			else
				encodedPasswordAnswer   =   passwordAnswer;
			if (!SecUtility.ValidateParameter(ref encodedPasswordAnswer, RequiresQuestionAndAnswer, true, false, 128))
			{
				status                  =   MembershipCreateStatus.InvalidAnswer;
				return null;
			}

			if( !SecUtility.ValidateParameter( ref username,true, true, true, 256))
			{
				status                  =   MembershipCreateStatus.InvalidUserName;
				return null;
			}

			if( !SecUtility.ValidateParameter( ref email,RequiresUniqueEmail,RequiresUniqueEmail,false,256 ) )
			{
				status                  =   MembershipCreateStatus.InvalidEmail;
				return null;
			}

			if( !SecUtility.ValidateParameter( ref passwordQuestion, RequiresQuestionAndAnswer, true, false, 256))
			{
				status                  =   MembershipCreateStatus.InvalidQuestion;
				return null;
			}

			if ( providerUserKey != null )
			{
				if ( !( providerUserKey is Guid ) )
				{
					status              =   MembershipCreateStatus.InvalidProviderUserKey;
					return null;
				}
			}

			if( password.Length < MinRequiredPasswordLength )
			{
				status                  =   MembershipCreateStatus.InvalidPassword;
				return null;
			}

			int count                   =   0;

			for( int i = 0; i < password.Length; i++ )
			{
				if( !char.IsLetterOrDigit( password, i ) )
				{
					count++;
				}
			}

			if( count < MinRequiredNonAlphanumericCharacters )
			{
				status                  =   MembershipCreateStatus.InvalidPassword;
				return null;
			}

			if( PasswordStrengthRegularExpression.Length > 0 )
			{
				if( !Regex.IsMatch( password, PasswordStrengthRegularExpression ) )
				{
					status              =   MembershipCreateStatus.InvalidPassword;
					return null;
				}
			}

			ValidatePasswordEventArgs e =   new ValidatePasswordEventArgs( username, password, true );
			OnValidatingPassword( e );

			if( e.Cancel )
			{
				status                  =   MembershipCreateStatus.InvalidPassword;
				return null;
			}
			
			// extract parameters for CRM from context
			int typeCode;
			Guid CrmImpersonateId	    =	Guid.Empty;
			string CrmImpersonateDomain	=	string.Empty;
			string CrmImpersonateLogin	=	string.Empty;
			string CrmImpersonatePwd	=	string.Empty;
			string EncodedCrmPwd	    =	string.Empty;
			bool   CrmIsCrmUser         =   false;
			try
			{
				HttpContext context     =   HttpContext.Current;
				typeCode                =   (int)context.Items["CrmTypeCode"];
				CrmImpersonateId        =   (Guid)context.Items["CrmImpersonateId"];
				CrmImpersonateDomain    =   (string)context.Items["CrmImpersonateDomain"];
				CrmImpersonateLogin     =   (string)context.Items["CrmImpersonateLogin"];
				CrmImpersonatePwd       =   (string)context.Items["CrmImpersonatePwd"];
				EncodedCrmPwd           =   EncodeCrmPassword(CrmImpersonatePwd);
				CrmIsCrmUser            =   (bool)context.Items["CrmIsCrmUser"];
				if ( SecurityTraceSwitch.Sw.TraceVerbose )
					 Trace.WriteLine( string.Format(CultureInfo.InvariantCulture,"[V]AddonNiceMembershipProvider CreateUser extracted from context typeCode: {0}, CrmImpersonateId: {1}, CrmImpersonateDomain: '{2}', CrmImpersonateLogin: '{3}', EncodedCrmPwd: '{4}', CrmIsCrmUser: {5}", 
						 new object[]{typeCode, CrmImpersonateId,CrmImpersonateDomain,CrmImpersonateLogin,EncodedCrmPwd,CrmIsCrmUser}),SecurityTraceSwitch.Sw.Info);
			}
			catch(Exception ex)
			{
				if ( SecurityTraceSwitch.Sw.TraceError )
					Trace.WriteLine( string.Format(CultureInfo.InvariantCulture,"[E]AddonNiceMembershipProvider CreateUser extracting Crm parameters from context portalID: {0}, username: {1}, ex:{2} ", 
						PortalID, username, ex),SecurityTraceSwitch.Sw.Info);
				status                  =   MembershipCreateStatus.ProviderError;
				return null;
			}
			
			try
			{
				// first check if user is already in CRM
				CrmCustomerId	CustomerId	=	null;
				try
				{
					if ( SecurityTraceSwitch.Sw.TraceVerbose )
						 Trace.WriteLine( string.Format(CultureInfo.InvariantCulture,"[V]AddonNiceMembershipProvider CreateUser before GetCustomerFromCRM portalID: {0}, typeCode: {1},username: {2}, CrmImpersonateId: {3}", 
							 new object[]{PortalID, typeCode, username,CrmImpersonateId}),SecurityTraceSwitch.Sw.Info);
					// Try to find it
					CustomerId          =   GetCustomerFromCRM(username, typeCode);
					if ( SecurityTraceSwitch.Sw.TraceVerbose )
						 Trace.WriteLine( string.Format(CultureInfo.InvariantCulture,"[V]AddonNiceMembershipProvider CreateUser after GetCustomerFromCRM portalID: {0}, typeCode: {1},username: {2}, CrmImpersonateId: {3}, CustomerId is null: {4}", 
							 new object[]{PortalID, typeCode, username,CrmImpersonateId,CustomerId == null}),SecurityTraceSwitch.Sw.Info);
					// need to create it
					if ( CustomerId == null )
					{
							if ( SecurityTraceSwitch.Sw.TraceVerbose )
								Trace.WriteLine( string.Format(CultureInfo.InvariantCulture,"[V]AddonNiceMembershipProvider CreateUser after GetCustomerFromCRM portalID: {0}, typeCode: {1},username: {2}, CrmImpersonateId: {3}, Creating CustomerId.", 
									new object[]{PortalID, typeCode, username,CrmImpersonateId}),SecurityTraceSwitch.Sw.Info);
							CustomerId  =   CreateInCRM(username, typeCode,CrmImpersonateId);
							if ( SecurityTraceSwitch.Sw.TraceVerbose )
								Trace.WriteLine( string.Format(CultureInfo.InvariantCulture,"[V]AddonNiceMembershipProvider CreateUser after CreateInCRM portalID: {0}, typeCode: {1},username: {2}, CrmImpersonateId: {3}, CustomerId is null: {4}", 
									new object[]{PortalID, typeCode, username,CrmImpersonateId,CustomerId == null}),SecurityTraceSwitch.Sw.Info);
					}
					if (CustomerId == null)
					{
						if ( SecurityTraceSwitch.Sw.TraceError )
							Trace.WriteLine( string.Format(CultureInfo.InvariantCulture,"[E]AddonNiceMembershipProvider CreateUser CRMCustomerId null after create in Crm portalID: {0}, typeCode: {1},username: {2}.", 
								PortalID, typeCode, username),SecurityTraceSwitch.Sw.Info);
						status                  =   MembershipCreateStatus.ProviderError;
						return null;
					}
				}
				catch (Exception ex)
				{
					if ( SecurityTraceSwitch.Sw.TraceError )
						Trace.WriteLine( string.Format(CultureInfo.InvariantCulture,"[E]AddonNiceMembershipProvider CreateUser Crm error portalID: {0}, typeCode: {1},username: {2}, ex: {3} ", 
							new object[] { PortalID, typeCode, username, ex }),SecurityTraceSwitch.Sw.Info);
						status                  =   MembershipCreateStatus.ProviderError;
						return null;
				}
				if ( SecurityTraceSwitch.Sw.TraceVerbose )
					Trace.WriteLine( string.Format(CultureInfo.InvariantCulture,"[V]AddonNiceMembershipProvider CreateUser created in Crm creating in DB UserName: {0}", username),SecurityTraceSwitch.Sw.Info);
				// try to add new user in DB
				SqlConnectionHolder holder = null;
				try 
				{
					if ( SecurityTraceSwitch.Sw.TraceVerbose )
						Trace.WriteLine( string.Format(CultureInfo.InvariantCulture,"[V]AddonNiceMembershipProvider CreateUser Adding new user in local DB portalID: {0}, typeCode: {1},username: {2}, CrmImpersonateId: {3}, CustomerId is null: {4}", 
							new object[]{PortalID, typeCode, username,CrmImpersonateId,CustomerId == null}),SecurityTraceSwitch.Sw.Info);
					holder                  =   SqlConnectionHelper.GetConnection( _sqlConnectionString, true );
					CheckSchemaVersion( holder.Connection );

					DateTime    dt          =   RoundToSeconds(DateTime.UtcNow);
					SqlCommand  cmd         =   new SqlCommand("dbo.AddonNice_Membership_CreateUser", holder.Connection);

					cmd.CommandTimeout      =   CommandTimeout;
					cmd.CommandType         =   CommandType.StoredProcedure;
					cmd.Parameters.Add(CreateInputParam("@ApplicationName", SqlDbType.NVarChar, ApplicationName));
					cmd.Parameters.Add(CreateInputParam("@UserName", SqlDbType.NVarChar, username));
					cmd.Parameters.Add(CreateInputParam("@Password", SqlDbType.NVarChar, pass));
					cmd.Parameters.Add(CreateInputParam("@PasswordSalt", SqlDbType.NVarChar, salt));
					cmd.Parameters.Add(CreateInputParam("@Email", SqlDbType.NVarChar, email));
					cmd.Parameters.Add(CreateInputParam("@PasswordQuestion", SqlDbType.NVarChar, passwordQuestion));
					cmd.Parameters.Add(CreateInputParam("@PasswordAnswer", SqlDbType.NVarChar, encodedPasswordAnswer));
					cmd.Parameters.Add(CreateInputParam("@IsApproved", SqlDbType.Bit, isApproved));
					cmd.Parameters.Add(CreateInputParam("@UniqueEmail", SqlDbType.Int, RequiresUniqueEmail ? 1 : 0));
					cmd.Parameters.Add(CreateInputParam("@PasswordFormat", SqlDbType.Int, (int)PasswordFormat));
					cmd.Parameters.Add(CreateInputParam("@CurrentTimeUtc", SqlDbType.DateTime, dt));
					SqlParameter p          =   CreateInputParam("@UserId", SqlDbType.UniqueIdentifier, providerUserKey);
					p.Direction             =   ParameterDirection.InputOutput;
					cmd.Parameters.Add( p );
					// Added parameters for CRM 
					cmd.Parameters.Add(CreateInputParam("@CrmTypeCode", SqlDbType.Int,CustomerId.typeCode));
					cmd.Parameters.Add(CreateInputParam("@CrmCustomerId", SqlDbType.UniqueIdentifier,CustomerId.CrmId));
					cmd.Parameters.Add(CreateInputParam("@CrmImpersonateId", SqlDbType.UniqueIdentifier,CrmImpersonateId));
					
					cmd.Parameters.Add(CreateInputParamSz("@CrmImpersonateDomain", SqlDbType.NVarChar,CrmImpersonateDomain,256));
					cmd.Parameters.Add(CreateInputParamSz("@CrmImpersonateLogin", SqlDbType.NVarChar,CrmImpersonateLogin,256));
					cmd.Parameters.Add(CreateInputParamSz("@CrmImpersonatePwd", SqlDbType.NVarChar,EncodedCrmPwd,256));
					cmd.Parameters.Add(CreateInputParam("@CrmIsCrmUser", SqlDbType.Bit,CrmIsCrmUser));

					p                       =   new SqlParameter("@ReturnValue", SqlDbType.Int);
					p.Direction             =   ParameterDirection.ReturnValue;
					cmd.Parameters.Add(p);
					cmd.ExecuteNonQuery();
					int iStatus             =   ((p.Value!=null) ? ((int) p.Value) : -1);
					if ( SecurityTraceSwitch.Sw.TraceVerbose )
						Trace.WriteLine( string.Format(CultureInfo.InvariantCulture,"[V]AddonNiceMembershipProvider CreateUser Added new user in local DB portalID: {0}, typeCode: {1},username: {2}, CrmImpersonateId: {3}, iStatus: {4}", 
							new object[]{PortalID, typeCode, username,CrmImpersonateId,iStatus}),SecurityTraceSwitch.Sw.Info);
					if (iStatus < 0 || iStatus > (int) MembershipCreateStatus.ProviderError)
						iStatus             =   (int) MembershipCreateStatus.ProviderError;
					status                  =   (MembershipCreateStatus) iStatus;
					if (iStatus != 0) // !success
					{
						if ( SecurityTraceSwitch.Sw.TraceError )
							Trace.WriteLine( string.Format(CultureInfo.InvariantCulture,"[E]AddonNiceMembershipProvider CreateUser Error Adding new user in local DB portalID: {0}, typeCode: {1},username: {2}, CrmImpersonateId: {3}, Status: {4}", 
								new object[]{PortalID, typeCode, username,CrmImpersonateId,status}),SecurityTraceSwitch.Sw.Info);
						return null;
					}
					string strUserKey       =   cmd.Parameters[ "@UserId" ].Value.ToString();
					if ( SecurityTraceSwitch.Sw.TraceVerbose )
						Trace.WriteLine( string.Format(CultureInfo.InvariantCulture,"[V]AddonNiceMembershipProvider CreateUser Added new user in local DB portalID: {0}, typeCode: {1},username: {2}, CrmImpersonateId: {3}, providerUserKey: {4}", 
							new object[]{PortalID, typeCode, username,CrmImpersonateId,strUserKey}),SecurityTraceSwitch.Sw.Info);
					providerUserKey         =   new Guid( strUserKey );
					dt                      =   dt.ToLocalTime();
					return new AddonNiceMembershipUser( this.Name,
											   username,
											   providerUserKey,
											   CustomerId,
											   email,
											   passwordQuestion,
											   null,
											   isApproved,
											   false,
											   dt,
											   dt,
											   dt,
											   new DateTime( 1754, 1, 1 ),
											   new DateTime( 1754, 1, 1 ),
											   PortalID,
											   ApplicationName,
											   CrmImpersonateId,
											   CrmImpersonateDomain,CrmImpersonateLogin,CrmImpersonatePwd,CrmIsCrmUser
											   );
				}
				finally
				{
					if( holder != null )
					{
						holder.Close();
						holder = null;
					}
				}
			} 
			catch(Exception ex) 
			{
				if ( SecurityTraceSwitch.Sw.TraceError )
					Trace.WriteLine( string.Format(CultureInfo.InvariantCulture,"[E]AddonNiceMembershipProvider CreateUser Error portalID: {0}, typeCode: {1},username: {2}, ex: {3}", 
						new object[]{PortalID, typeCode, username,ex}),SecurityTraceSwitch.Sw.Info);
				throw;
			}
		}

		#endregion Create User

		#region special Login for Crm users
		
		/// <summary>
		/// based on the domain login name of user, try to find :
		/// 1) a crm user 
		/// 2) a membership record
		/// if ( membership record doesn't exit, create it using the domainname as username and CrmDefault user password as temp pwd for membership
		/// The impersonate id is the CrmDefault user
		/// -> user wil have to change its impersonate user later and enter its real password to impersonate on itself
		/// -> a task will be automatically created for this to its Crm activities
		/// </summary>
		public bool AutoLogCrmUser(FormsAuthenticationEventArgs args,bool persist)
		{
			bool ret                            =   false;
			HttpResponse Response               =   args.Context.Response;
			HttpRequest Request                 =   args.Context.Request;
			ADNDynSystemUser suser              =   Wrapper.Util.FindSystemUserByDomainName(Request.LogonUserIdentity.Name);
			if (SecurityTraceSwitch.Sw.TraceVerbose)
				Trace.WriteLine( string.Format(CultureInfo.InvariantCulture,"[V]AddonNiceMembershipProvider AutoLogCrmUser BEG SystemUser LogonUser: {0}, found: {1}",Request.LogonUserIdentity.Name,(suser != null)),SecurityTraceSwitch.Sw.Info);
			if ( suser != null )
			{
				AddonNiceMembershipUser muser   =   (AddonNiceMembershipUser)GetUser(suser.domainname,false);
				if (SecurityTraceSwitch.Sw.TraceVerbose)
					Trace.WriteLine( string.Format(CultureInfo.InvariantCulture,"[V]AddonNiceMembershipProvider AutoLogCrmUser Membership User found: {0}",muser != null),SecurityTraceSwitch.Sw.Info);
				if  (muser == null )
				{
					if ( suser.systemuserid == Wrapper.adminUserId )
						muser                   =   (AddonNiceMembershipUser)CreateAdmin();
					else
						muser                   =   (AddonNiceMembershipUser)CreateFromCrmUser(suser);
					if (SecurityTraceSwitch.Sw.TraceVerbose)
						Trace.WriteLine( string.Format(CultureInfo.InvariantCulture,"[V]AddonNiceMembershipProvider AutoLogCrmUser Membership User created: {0}",muser != null),SecurityTraceSwitch.Sw.Info);
				}
				// Check user and generate the authentication cookie with membership data inside
				if ( ( muser != null ) && ValidateUser(muser.UserName, muser.CrmImpersonatePwd))
				{
					string userData             =   muser.UserData;
					if (SecurityTraceSwitch.Sw.TraceVerbose)
						Trace.WriteLine( string.Format(CultureInfo.InvariantCulture,"[V]AddonNiceMembershipProvider AutoLogCrmUser create FormsAuthenticationTicket, Name: {0} , USerData: {1}", 
							muser.UserName,userData),SecurityTraceSwitch.Sw.Info);
					HttpCookie cookie           =   PortalSecurity.SetAuthCookie(muser.UserName,muser.UserData,persist);
					if ( Response.Cookies.Get(cookie.Name) == null ) // normally added by SetAuthCookie
						Response.Cookies.Add(cookie); 
					if ( Request.Cookies.Get(cookie.Name) == null ) // normally adding to response adds to request
						Request.Cookies.Add(cookie);
					ret                         =   true;
				 }
			}
			if (SecurityTraceSwitch.Sw.TraceVerbose)
				Trace.WriteLine( string.Format(CultureInfo.InvariantCulture,"[V]AddonNiceMembershipProvider AutoLogCrmUser END : {0}",ret),SecurityTraceSwitch.Sw.Info);
			return ret;
		}

		#endregion special Login for Crm users


		#region Pwd related methods

		public override bool ChangePasswordQuestionAndAnswer(string username, string password, string newPasswordQuestion, string newPasswordAnswer)
		{
			if ( SecurityTraceSwitch.Sw.TraceVerbose )
				Trace.WriteLine( string.Format(CultureInfo.InvariantCulture,"[V]AddonNiceMembershipProvider ChangePasswordQuestionAndAnswer BEG portalID: {0}, username: {1}, password: {2}, PasswordQuestion: {3}, newPasswordAnswer: {4}", 
					new object[]{PortalID, username,password,newPasswordQuestion, newPasswordAnswer}),SecurityTraceSwitch.Sw.Info);
			SecUtility.CheckParameter( ref username, true, true, true, 256, "username" );
			SecUtility.CheckParameter( ref password, true, true, false, 128, "password" );

			string salt;
			int passwordFormat;
			if (!CheckPassword(username, password, false, false, out salt, out passwordFormat))
			{
				if ( SecurityTraceSwitch.Sw.TraceVerbose )
					Trace.WriteLine( string.Format(CultureInfo.InvariantCulture,"[V]AddonNiceMembershipProvider ChangePasswordQuestionAndAnswer failed portalID: {0}, username: {1}", 
						PortalID, username),SecurityTraceSwitch.Sw.Info);
				return false;
			}
			SecUtility.CheckParameter(ref newPasswordQuestion, RequiresQuestionAndAnswer, RequiresQuestionAndAnswer, false, 256, "newPasswordQuestion");
			string encodedPasswordAnswer;
			if( newPasswordAnswer != null )
			{
				newPasswordAnswer           =   newPasswordAnswer.Trim();
			}

			SecUtility.CheckParameter(ref newPasswordAnswer, RequiresQuestionAndAnswer, RequiresQuestionAndAnswer, false, 128, "newPasswordAnswer");
			if (!string.IsNullOrEmpty(newPasswordAnswer)) 
			{
				encodedPasswordAnswer       =   EncodePassword(newPasswordAnswer.ToLower(CultureInfo.InvariantCulture), (int)passwordFormat, salt);
			}
			else
				encodedPasswordAnswer       =   newPasswordAnswer;
			SecUtility.CheckParameter(ref encodedPasswordAnswer, RequiresQuestionAndAnswer, RequiresQuestionAndAnswer, false, 128, "newPasswordAnswer");

			try 
			{
				SqlConnectionHolder holder = null;
				try 
				{
					holder                  =   SqlConnectionHelper.GetConnection( _sqlConnectionString, true );
					CheckSchemaVersion( holder.Connection );

					SqlCommand    cmd       =   new SqlCommand("dbo.AddonNice_Membership_ChangePasswordQuestionAndAnswer", holder.Connection);

					cmd.CommandTimeout      =   CommandTimeout;
					cmd.CommandType         =   CommandType.StoredProcedure;
					cmd.Parameters.Add(CreateInputParam("@ApplicationName", SqlDbType.NVarChar, ApplicationName));
					cmd.Parameters.Add(CreateInputParam("@UserName", SqlDbType.NVarChar, username));
					cmd.Parameters.Add(CreateInputParam("@NewPasswordQuestion", SqlDbType.NVarChar, newPasswordQuestion));
					cmd.Parameters.Add(CreateInputParam("@NewPasswordAnswer", SqlDbType.NVarChar, encodedPasswordAnswer));

					SqlParameter p          =   new SqlParameter("@ReturnValue", SqlDbType.Int);
					p.Direction             =   ParameterDirection.ReturnValue;
					cmd.Parameters.Add(p);

					cmd.ExecuteNonQuery();
					int status              =   ( ( p.Value != null ) ? ( ( int )p.Value ) : -1 );
					if ( SecurityTraceSwitch.Sw.TraceVerbose )
						Trace.WriteLine( string.Format(CultureInfo.InvariantCulture,"[V]AddonNiceMembershipProvider ChangePasswordQuestionAndAnswer after ExecuteNonQuery portalID: {0}, username: {1}, status: {2}", 
							PortalID, username,status),SecurityTraceSwitch.Sw.Info);
					if( status != 0 )
					{
						throw new ProviderException( GetExceptionText( status ) );
					}
					return ( status == 0 );
				}
				finally
				{
					if( holder != null )
					{
						holder.Close();
						holder = null;
					}
				}
			} 
			catch(Exception ex) 
			{
				if ( SecurityTraceSwitch.Sw.TraceError )
					Trace.WriteLine( string.Format(CultureInfo.InvariantCulture,"[E]AddonNiceMembershipProvider ChangePasswordQuestionAndAnswer Error portalID: {0}, username: {1}, ex: {2}", 
						PortalID,username,ex),SecurityTraceSwitch.Sw.Info);
				throw;
			}
		}

		public override string GetPassword(string username, string passwordAnswer)
		{
			if ( SecurityTraceSwitch.Sw.TraceVerbose )
				Trace.WriteLine( string.Format(CultureInfo.InvariantCulture,"[V]AddonNiceMembershipProvider GetPassword BEG portalID: {0}, username: {1}, EnablePasswordRetrieval: {2}",
						PortalID, username, EnablePasswordRetrieval),SecurityTraceSwitch.Sw.Info); 
			if ( !EnablePasswordRetrieval )
			{
				throw new NotSupportedException( SR.GetString( SR.Membership_PasswordRetrieval_not_supported ) );
			}

			SecUtility.CheckParameter( ref username, true, true, true, 256, "username" );

			string encodedPasswordAnswer    =   GetEncodedPasswordAnswer(username, passwordAnswer);
			SecUtility.CheckParameter(ref encodedPasswordAnswer, RequiresQuestionAndAnswer, RequiresQuestionAndAnswer, false, 128, "passwordAnswer");

			string errText;
			int passwordFormat              =   0;
			int status                      =   0;

			string pass                     =   GetPasswordFromDB(username, encodedPasswordAnswer, RequiresQuestionAndAnswer, out passwordFormat, out status);

			if ( SecurityTraceSwitch.Sw.TraceVerbose )
				Trace.WriteLine( string.Format(CultureInfo.InvariantCulture,"[V]AddonNiceMembershipProvider GetPassword BEG portalID: {0}, username: {1}, pass is null: {2}",
					PortalID, username, (pass == null)),SecurityTraceSwitch.Sw.Info); 
			if ( pass == null )
			{
				errText                     =   GetExceptionText( status );
				if ( IsStatusDueToBadPassword( status ) )
				{
					throw new MembershipPasswordException( errText );
				}
				throw new ProviderException( errText );
			}
			return UnEncodePassword( pass, passwordFormat );
		}

		public bool CheckPwd(string newPassword)
		{
			if( newPassword.Length < MinRequiredPasswordLength )
			{
				if ( SecurityTraceSwitch.Sw.TraceVerbose )
					Trace.WriteLine( string.Format(CultureInfo.InvariantCulture,"[V]AddonNiceMembershipProvider CheckPwd portalID: {0}, newPassword.Length: {1} < MinRequiredPasswordLength: {2}",
						new object[] { PortalID, newPassword.Length,MinRequiredPasswordLength}),SecurityTraceSwitch.Sw.Info); 
				throw new ArgumentException(SR.GetString(
							  SR.Password_too_short,
							  "newPassword",
							  MinRequiredPasswordLength.ToString(CultureInfo.InvariantCulture)));
			}

			int count = 0;

			for( int i = 0; i < newPassword.Length; i++ )
			{
				if( !char.IsLetterOrDigit( newPassword, i ) )
				{
					count++;
				}
			}

			if( count < MinRequiredNonAlphanumericCharacters )
			{
				if ( SecurityTraceSwitch.Sw.TraceVerbose )
					Trace.WriteLine( string.Format(CultureInfo.InvariantCulture,"[V]AddonNiceMembershipProvider CheckPwd portalID: {0}, count: {1} < MinRequiredNonAlphanumericCharacters: {2}",
						new object[] { PortalID, count ,MinRequiredNonAlphanumericCharacters }),SecurityTraceSwitch.Sw.Info); 
				throw new ArgumentException(SR.GetString(
							  SR.Password_need_more_non_alpha_numeric_chars,
							  "newPassword",
							  MinRequiredNonAlphanumericCharacters.ToString(CultureInfo.InvariantCulture)));
			}

			if( PasswordStrengthRegularExpression.Length > 0 )
			{
				if( !Regex.IsMatch( newPassword, PasswordStrengthRegularExpression ) )
				{
					if ( SecurityTraceSwitch.Sw.TraceVerbose )
						Trace.WriteLine( string.Format(CultureInfo.InvariantCulture,"[V]AddonNiceMembershipProvider CheckPwd portalID: {0}, Regex not matched PasswordStrengthRegularExpression: {1}",
							new object[] { PortalID, PasswordStrengthRegularExpression }),SecurityTraceSwitch.Sw.Info); 
					throw new ArgumentException(SR.GetString(SR.Password_does_not_match_regular_expression,
															 "newPassword"));
				}
			}
			return true;
		}

		public override bool ChangePassword(string username, string oldPassword, string newPassword)
		{
			if ( SecurityTraceSwitch.Sw.TraceVerbose )
				Trace.WriteLine( string.Format(CultureInfo.InvariantCulture,"[V]AddonNiceMembershipProvider ChangePassword BEG portalID: {0}, username: {1}",
					PortalID, username),SecurityTraceSwitch.Sw.Info); 
			SecUtility.CheckParameter( ref username, true, true, true, 256, "username" );
			SecUtility.CheckParameter( ref oldPassword, true, true, false, 128, "oldPassword" );
			SecUtility.CheckParameter( ref newPassword, true, true, false, 128, "newPassword" );

			string salt             =   null;
			int passwordFormat;
			int status;

			if (!CheckPassword( username, oldPassword, false, false, out salt, out passwordFormat))
			   return false;

			CheckPwd(newPassword);

			string pass         =   EncodePassword(newPassword, (int)passwordFormat, salt);
			if ( pass.Length > 128 )
			{
					if ( SecurityTraceSwitch.Sw.TraceVerbose )
						Trace.WriteLine( string.Format(CultureInfo.InvariantCulture,"[V]AddonNiceMembershipProvider ChangePassword BEG portalID: {0}, username: {1}, pass.Length: {2} > 128",
							new object[] { PortalID, username,pass.Length }),SecurityTraceSwitch.Sw.Info); 
				throw new ArgumentException(SR.GetString(SR.Membership_password_too_long), "newPassword");
			}

			ValidatePasswordEventArgs e = new ValidatePasswordEventArgs( username, newPassword, false );
			OnValidatingPassword( e );

			if( e.Cancel )
			{
				if ( SecurityTraceSwitch.Sw.TraceVerbose )
					Trace.WriteLine( string.Format(CultureInfo.InvariantCulture,"[V]AddonNiceMembershipProvider ChangePassword BEG portalID: {0}, username: {1}, OnValidatingPassword canceled",
							PortalID, username),SecurityTraceSwitch.Sw.Info); 
				if( e.FailureInformation != null )
				{
					throw e.FailureInformation;
				}
				throw new ArgumentException( SR.GetString( SR.Membership_Custom_Password_Validation_Failure ), "newPassword");
			}


			try 
			{
				SqlConnectionHolder holder = null;
				try 
				{
					holder                  =   SqlConnectionHelper.GetConnection( _sqlConnectionString, true );
					CheckSchemaVersion( holder.Connection );

					SqlCommand  cmd         =   new SqlCommand( "dbo.AddonNice_Membership_SetPassword", holder.Connection );

					cmd.CommandTimeout      =   CommandTimeout;
					cmd.CommandType         =   CommandType.StoredProcedure;
					cmd.Parameters.Add(CreateInputParam("@ApplicationName", SqlDbType.NVarChar, ApplicationName));
					cmd.Parameters.Add(CreateInputParam("@UserName", SqlDbType.NVarChar, username));
					cmd.Parameters.Add(CreateInputParam("@NewPassword", SqlDbType.NVarChar, pass));
					cmd.Parameters.Add(CreateInputParam("@PasswordSalt", SqlDbType.NVarChar, salt));
					cmd.Parameters.Add(CreateInputParam("@PasswordFormat", SqlDbType.Int, passwordFormat));
					cmd.Parameters.Add(CreateInputParam("@CurrentTimeUtc", SqlDbType.DateTime, DateTime.UtcNow));

					SqlParameter p          =   new SqlParameter("@ReturnValue", SqlDbType.Int);
					p.Direction             =   ParameterDirection.ReturnValue;
					cmd.Parameters.Add(p);

					cmd.ExecuteNonQuery();

					status                  =  ( ( p.Value != null ) ? ( ( int )p.Value ) : -1 );
					if ( SecurityTraceSwitch.Sw.TraceVerbose )
						Trace.WriteLine( string.Format(CultureInfo.InvariantCulture,"[V]AddonNiceMembershipProvider ChangePassword portalID: {0}, username: {1}, status: {2}",
							PortalID, username,status),SecurityTraceSwitch.Sw.Info); 

					if ( status != 0 )
					{
						string errText      =   GetExceptionText( status );

						if ( IsStatusDueToBadPassword( status ) )
						{
							throw new MembershipPasswordException( errText );
						}
						throw new ProviderException( errText );
					}
					return true;
				}
				finally
				{
					if( holder != null )
					{
						holder.Close();
						holder = null;
					}
				}
			} 
			catch(Exception ex)
			{
				if ( SecurityTraceSwitch.Sw.TraceError )
					Trace.WriteLine( string.Format(CultureInfo.InvariantCulture,"[E]AddonNiceMembershipProvider ChangePassword Error portalID: {0}, username: {1}, ex: {2}",
							PortalID, username,ex),SecurityTraceSwitch.Sw.Info); 
				throw;
			}
		}

		public override string ResetPassword( string username, string passwordAnswer )
		{
			if ( SecurityTraceSwitch.Sw.TraceVerbose )
				Trace.WriteLine( string.Format(CultureInfo.InvariantCulture,"[V]AddonNiceMembershipProvider ResetPassword begin username: {0}, passwordAnswer: {1}",
					username,passwordAnswer),SecurityTraceSwitch.Sw.Info);
			if ( !EnablePasswordReset )
			{
				throw new NotSupportedException( SR.GetString( SR.Not_configured_to_support_password_resets ) );
			}

			SecUtility.CheckParameter( ref username, true, true, true, 256, "username" );

			string salt;
			int passwordFormat;
			string passwdFromDB;
			int status;
			int failedPasswordAttemptCount;
			int failedPasswordAnswerAttemptCount;
			bool isApproved;
			DateTime lastLoginDate, lastActivityDate;

			GetPasswordWithFormat(username, false, out status, out passwdFromDB, out passwordFormat, out salt, out failedPasswordAttemptCount,
								  out failedPasswordAnswerAttemptCount, out isApproved, out lastLoginDate, out lastActivityDate);
			if (status != 0)
			{
				if (IsStatusDueToBadPassword(status))
				{
					if ( SecurityTraceSwitch.Sw.TraceVerbose )
						Trace.WriteLine( string.Format(CultureInfo.InvariantCulture,"[V]AddonNiceMembershipProvider ResetPassword status != 0 IsStatusDueToBadPassword is true, username: {0}, passwordAnswer: {1}",
							username,passwordAnswer),SecurityTraceSwitch.Sw.Info);
					throw new MembershipPasswordException(GetExceptionText(status));
				}
				else
				{
					if ( SecurityTraceSwitch.Sw.TraceVerbose )
						Trace.WriteLine( string.Format(CultureInfo.InvariantCulture,"[V]AddonNiceMembershipProvider ResetPassword status != 0 IsStatusDueToBadPassword is false, username: {0}, passwordAnswer: {1}",
							username,passwordAnswer),SecurityTraceSwitch.Sw.Info);
					throw new ProviderException(GetExceptionText(status));
				}
			}

			string encodedPasswordAnswer;
			if( passwordAnswer != null )
			{
				passwordAnswer = passwordAnswer.Trim();
			}
			if (!string.IsNullOrEmpty(passwordAnswer))
				encodedPasswordAnswer = EncodePassword(passwordAnswer.ToLower(CultureInfo.InvariantCulture), passwordFormat, salt);
			else
				encodedPasswordAnswer = passwordAnswer;
			SecUtility.CheckParameter(ref encodedPasswordAnswer, RequiresQuestionAndAnswer, RequiresQuestionAndAnswer, false, 128, "passwordAnswer");
			string newPassword  = GeneratePassword();

			ValidatePasswordEventArgs e = new ValidatePasswordEventArgs( username, newPassword, false );
			OnValidatingPassword( e );

			if( e.Cancel )
			{
				if ( SecurityTraceSwitch.Sw.TraceVerbose )
					Trace.WriteLine( string.Format(CultureInfo.InvariantCulture,"[V]AddonNiceMembershipProvider ResetPassword validating canceled, username: {0}, passwordAnswer: {1}",
						username,passwordAnswer),SecurityTraceSwitch.Sw.Info);
				if( e.FailureInformation != null )
				{
					throw e.FailureInformation;
				}
				else
				{
					throw new ProviderException( SR.GetString( SR.Membership_Custom_Password_Validation_Failure ) );
				}
			}


			try
			{
				SqlConnectionHolder holder = null;
				try 
				{
					holder = SqlConnectionHelper.GetConnection( _sqlConnectionString, true );
					CheckSchemaVersion( holder.Connection );

					SqlCommand    cmd     = new SqlCommand("dbo.AddonNice_Membership_ResetPassword", holder.Connection);
					string        errText;

					cmd.CommandTimeout = CommandTimeout;
					cmd.CommandType = CommandType.StoredProcedure;
					cmd.Parameters.Add(CreateInputParam("@ApplicationName", SqlDbType.NVarChar, ApplicationName));
					cmd.Parameters.Add(CreateInputParam("@UserName", SqlDbType.NVarChar, username));
					cmd.Parameters.Add(CreateInputParam("@NewPassword", SqlDbType.NVarChar, EncodePassword(newPassword, (int) passwordFormat, salt)));
					cmd.Parameters.Add(CreateInputParam("@MaxInvalidPasswordAttempts", SqlDbType.Int, MaxInvalidPasswordAttempts ) );
					cmd.Parameters.Add(CreateInputParam("@PasswordAttemptWindow", SqlDbType.Int, PasswordAttemptWindow ) );
					cmd.Parameters.Add(CreateInputParam("@PasswordSalt", SqlDbType.NVarChar, salt));
					cmd.Parameters.Add(CreateInputParam("@PasswordFormat", SqlDbType.Int, (int)passwordFormat));
					cmd.Parameters.Add(CreateInputParam("@CurrentTimeUtc", SqlDbType.DateTime, DateTime.UtcNow));
					if (RequiresQuestionAndAnswer) {
						cmd.Parameters.Add(CreateInputParam("@PasswordAnswer", SqlDbType.NVarChar, encodedPasswordAnswer));
					}

					SqlParameter p = new SqlParameter("@ReturnValue", SqlDbType.Int);
					p.Direction = ParameterDirection.ReturnValue;
					cmd.Parameters.Add(p);

					cmd.ExecuteNonQuery();

					status = ( ( p.Value != null ) ? ( ( int )p.Value ) : -1 );
					if ( SecurityTraceSwitch.Sw.TraceVerbose )
						Trace.WriteLine( string.Format(CultureInfo.InvariantCulture,"[V]AddonNiceMembershipProvider ResetPassword username: {0}, passwordAnswer: {1}, status: {2}",
							username,passwordAnswer, status),SecurityTraceSwitch.Sw.Info);

					if ( status != 0 )
					{
						errText = GetExceptionText( status );

						if ( IsStatusDueToBadPassword( status ) )
						{
							if ( SecurityTraceSwitch.Sw.TraceError )
								Trace.WriteLine( string.Format(CultureInfo.InvariantCulture,"[E]AddonNiceMembershipProvider ResetPassword Status is Due To Bad Password username: {0}, passwordAnswer: {1}, errText: {2}",
									username,passwordAnswer, errText),SecurityTraceSwitch.Sw.Info);
							throw new MembershipPasswordException( errText );
						}
						else
						{
							if ( SecurityTraceSwitch.Sw.TraceError )
								Trace.WriteLine( string.Format(CultureInfo.InvariantCulture,"[E]AddonNiceMembershipProvider ResetPassword Status is not Due To Bad Password username: {0}, passwordAnswer: {1}, errText: {2}",
									username,passwordAnswer, errText),SecurityTraceSwitch.Sw.Info);
							throw new ProviderException( errText );
						}
					}
					if ( SecurityTraceSwitch.Sw.TraceVerbose )
						Trace.WriteLine( string.Format(CultureInfo.InvariantCulture,"[V]AddonNiceMembershipProvider ResetPassword END username: {0}, passwordAnswer: {1}",
							username,passwordAnswer),SecurityTraceSwitch.Sw.Info);
					return newPassword;
				}
				finally
				{
					if( holder != null )
					{
						holder.Close();
						holder = null;
					}
				}
			} 
			catch 
			{
				throw;
			}
		}

		#endregion Pwd related methods

		#region Update user

		/// <summary>
		/// This method allow to update  Email, Comment, IsApproved ,LastLoginDate 
		/// IT doesn't allow to update the CRM elements
		/// </summary>
		public override void UpdateUser(MembershipUser user0)
		{
			if( user0 == null )
			{
				if ( SecurityTraceSwitch.Sw.TraceError )
					Trace.WriteLine( string.Format(CultureInfo.InvariantCulture,"[E]AddonNiceMembershipProvider UpdateUser Error portalID: {0}, user null.",PortalID),SecurityTraceSwitch.Sw.Info); 
				throw new ArgumentNullException( "user" );
			}
			if( !(user0 is AddonNiceMembershipUser ) )
			{
				if ( SecurityTraceSwitch.Sw.TraceError )
					Trace.WriteLine( string.Format(CultureInfo.InvariantCulture,"[E]AddonNiceMembershipProvider UpdateUser Error portalID: {0}, user is not AddonNiceMembershipUser ",
						PortalID),SecurityTraceSwitch.Sw.Info); 
				throw new ProviderException( "UpdateUser Not CRMMembershipUser" );
			}

			AddonNiceMembershipUser user    = (AddonNiceMembershipUser) user0;
			if ( SecurityTraceSwitch.Sw.TraceVerbose )
				Trace.WriteLine( string.Format(CultureInfo.InvariantCulture,"[V]AddonNiceMembershipProvider UpdateUser begin username: {0},user.typeName: {1},user.ProviderName: {2}",
					user.UserName,user.typeName,user.ProviderName),SecurityTraceSwitch.Sw.Info);

			string temp                     =   user.UserName;
			SecUtility.CheckParameter( ref temp, true, true, true, 256, "UserName" );
			temp                            =   user.Email;
			SecUtility.CheckParameter( ref temp,RequiresUniqueEmail,RequiresUniqueEmail,false,256,"Email");
			user.Email                      =   temp;
			
			// Extract parameters for CRM from user
			int   typeCode                  =   user.typeCode;
			Guid  CrmImpersonateId	        =	user.CrmImpersonateId;
			Guid  CrmId                     =   user.CustomerId.CrmId;
			string CrmImpersonateDomain	    =	user.CrmImpersonateDomain;
			string CrmImpersonateLogin	    =	user.CrmImpersonateLogin;
			string CrmImpersonatePwd	    =	user.CrmImpersonatePwd;
			bool CrmIsCrmUser               =   user.CrmIsCrmUser;
			string EncodedCrmPwd	        =	string.Empty;
			bool changeCrmPwd               =   (user.PwdChanged && !string.IsNullOrEmpty(CrmImpersonatePwd));
			string password                 =   string.Empty;
			string pass                     =   string.Empty;
			string salt                     =   string.Empty;
			int passwordFormat              =   0;
			bool changeMembershipPwd        =   false;
			try 
			{
				// if crm pwd has been changed, reEncode
				if (changeCrmPwd)
				{
					EncodedCrmPwd           =   EncodeCrmPassword(CrmImpersonatePwd);
					// must also change Membership pwd if it is a Crm user
					if (CrmIsCrmUser)
					{
						password            =   CrmImpersonatePwd;
						string              passwdFromDB;
						int                 status;
						int                 failedPasswordAttemptCount;
						int                 failedPasswordAnswerAttemptCount;
						bool                isApproved;
						DateTime            lastLoginDate, lastActivityDate;

						GetPasswordWithFormat(user.UserName, false, out status, out passwdFromDB, out passwordFormat, out salt, out failedPasswordAttemptCount,
											  out failedPasswordAnswerAttemptCount, out isApproved, out lastLoginDate, out lastActivityDate);
						// could throw if not Ok
						CheckPwd(password);
						pass                =   EncodePassword(password, passwordFormat, salt);
						if ( pass.Length > 128 )
						{
								if ( SecurityTraceSwitch.Sw.TraceVerbose )
									Trace.WriteLine( string.Format(CultureInfo.InvariantCulture,"[V]AddonNiceMembershipProvider UpdateUser ChangePassword BEG portalID: {0}, username: {1}, pass.Length: {2} > 128",
										new object[] { PortalID, user.UserName,pass.Length }),SecurityTraceSwitch.Sw.Info); 
							throw new ArgumentException(SR.GetString(SR.Membership_password_too_long), "newPassword");
						}

						ValidatePasswordEventArgs e = new ValidatePasswordEventArgs( user.UserName, password, false );
						OnValidatingPassword( e );

						if( e.Cancel )
						{
							if ( SecurityTraceSwitch.Sw.TraceError )
								Trace.WriteLine( string.Format(CultureInfo.InvariantCulture,"[E]AddonNiceMembershipProvider UpdateUser ChangePassword BEG portalID: {0}, username: {1}, OnValidatingPassword canceled",
										PortalID, user.UserName),SecurityTraceSwitch.Sw.Info); 
							if( e.FailureInformation != null )
							{
								throw e.FailureInformation;
							}
							throw new ArgumentException( SR.GetString( SR.Membership_Custom_Password_Validation_Failure ), "newPassword");
						}
						changeMembershipPwd =   true;
					}
					UpdateInCRM(user);
				}
				
				SqlConnectionHolder holder  =   null;
				try 
				{
					holder                  =   SqlConnectionHelper.GetConnection( _sqlConnectionString, true );
					CheckSchemaVersion( holder.Connection );
					// no change from original proc
					SqlCommand    cmd       =   new SqlCommand("dbo.AddonNice_Membership_UpdateUser", holder.Connection);

					cmd.CommandTimeout      =   CommandTimeout;
					cmd.CommandType         =   CommandType.StoredProcedure;
					cmd.Parameters.Add(CreateInputParam("@ApplicationName", SqlDbType.NVarChar, ApplicationName));
					cmd.Parameters.Add(CreateInputParam("@UserName", SqlDbType.NVarChar, user.UserName));
					cmd.Parameters.Add(CreateInputParam("@Email", SqlDbType.NVarChar, user.Email));
					cmd.Parameters.Add(CreateInputParam("@Comment", SqlDbType.NText, user.Comment));
					cmd.Parameters.Add(CreateInputParam("@IsApproved", SqlDbType.Bit, user.IsApproved ? 1 : 0));
					cmd.Parameters.Add(CreateInputParam("@LastLoginDate", SqlDbType.DateTime, user.LastLoginDate.ToUniversalTime()));
					cmd.Parameters.Add(CreateInputParam("@LastActivityDate", SqlDbType.DateTime, user.LastActivityDate.ToUniversalTime()));
					cmd.Parameters.Add(CreateInputParam("@UniqueEmail", SqlDbType.Int, RequiresUniqueEmail ? 1 : 0));
					cmd.Parameters.Add(CreateInputParam("@CurrentTimeUtc", SqlDbType.DateTime, DateTime.UtcNow));

					// Added parameters for CRM 
					cmd.Parameters.Add(CreateInputParam("@CrmTypeCode", SqlDbType.Int,typeCode));
					cmd.Parameters.Add(CreateInputParam("@CrmCustomerId", SqlDbType.UniqueIdentifier,CrmId));
					cmd.Parameters.Add(CreateInputParam("@CrmImpersonateId", SqlDbType.UniqueIdentifier,CrmImpersonateId));

					cmd.Parameters.Add(CreateInputParam("@CrmImpersonateDomain", SqlDbType.NVarChar,CrmImpersonateDomain));
					cmd.Parameters.Add(CreateInputParam("@CrmImpersonateLogin", SqlDbType.NVarChar,CrmImpersonateLogin));
					cmd.Parameters.Add(CreateInputParam("@CrmIsCrmUser", SqlDbType.Bit,CrmIsCrmUser));

					// only add it if changed, else default value is Null and DB will not be updated
					if (changeCrmPwd)
						cmd.Parameters.Add(CreateInputParam("@CrmImpersonatePwd", SqlDbType.NVarChar,EncodedCrmPwd));

					SqlParameter p          =   new SqlParameter("@ReturnValue", SqlDbType.Int);
					p.Direction             =   ParameterDirection.ReturnValue;
					cmd.Parameters.Add(p);
					cmd.ExecuteNonQuery();
					int status              =   ((p.Value!=null) ? ((int) p.Value) : -1);
					if ( SecurityTraceSwitch.Sw.TraceVerbose )
						Trace.WriteLine( string.Format(CultureInfo.InvariantCulture,"[V]AddonNiceMembershipProvider UpdateUser portalID: {0}, typeCode: {1}, user.name: {2}, status: {3}",
							new object[] { PortalID, typeCode, user.UserName,status}),SecurityTraceSwitch.Sw.Info);
					if (status != 0)
					{
						if ( SecurityTraceSwitch.Sw.TraceError )
							Trace.WriteLine( string.Format(CultureInfo.InvariantCulture,"[E]AddonNiceMembershipProvider UpdateUser portalID: {0}, typeCode: {1}, user.name: {2}, status: {3}",
								new object[] { PortalID, typeCode, user.UserName,status}),SecurityTraceSwitch.Sw.Info); 
						throw new ProviderException(GetExceptionText(status));
					}
					
					if ( changeMembershipPwd )
					{
						cmd                     =   new SqlCommand( "dbo.AddonNice_Membership_SetPassword", holder.Connection );

						cmd.CommandTimeout      =   CommandTimeout;
						cmd.CommandType         =   CommandType.StoredProcedure;
						cmd.Parameters.Add(CreateInputParam("@ApplicationName", SqlDbType.NVarChar, ApplicationName));
						cmd.Parameters.Add(CreateInputParam("@UserName", SqlDbType.NVarChar, user.UserName));
						cmd.Parameters.Add(CreateInputParam("@NewPassword", SqlDbType.NVarChar, pass));
						cmd.Parameters.Add(CreateInputParam("@PasswordSalt", SqlDbType.NVarChar, salt));
						cmd.Parameters.Add(CreateInputParam("@PasswordFormat", SqlDbType.Int, passwordFormat));
						cmd.Parameters.Add(CreateInputParam("@CurrentTimeUtc", SqlDbType.DateTime, DateTime.UtcNow));

						p                       =   new SqlParameter("@ReturnValue", SqlDbType.Int);
						p.Direction             =   ParameterDirection.ReturnValue;
						cmd.Parameters.Add(p);

						cmd.ExecuteNonQuery();

						status                  =  ( ( p.Value != null ) ? ( ( int )p.Value ) : -1 );
						if ( SecurityTraceSwitch.Sw.TraceVerbose )
							Trace.WriteLine( string.Format(CultureInfo.InvariantCulture,"[V]AddonNiceMembershipProvider UpdateUser ChangePassword portalID: {0}, username: {1}, status: {2}",
								PortalID, user.UserName,status),SecurityTraceSwitch.Sw.Info); 

						if ( status != 0 )
						{
							string errText      =   GetExceptionText( status );

							if ( IsStatusDueToBadPassword( status ) )
							{
								throw new MembershipPasswordException( errText );
							}
							throw new ProviderException( errText );
						}
					}
					return;
				}
				finally
				{
					if( holder != null )
					{
						holder.Close();
						holder = null;
					}
				}
			} 
			catch(Exception ex) 
			{
				if ( SecurityTraceSwitch.Sw.TraceError )
					Trace.WriteLine( string.Format(CultureInfo.InvariantCulture,"[E]AddonNiceMembershipProvider UpdateUser Error portalID: {0}, typeCode: {1}, user.name: {2}, ex: {3}",
						new object[] { PortalID, typeCode, user.UserName,ex}),SecurityTraceSwitch.Sw.Info); 
				throw;
			}
		}

		
		/// <summary>
		/// This method allow to update  Email only: take the crmEmail and apply it to provider db
		/// </summary>
		public virtual void UpdateEmail(MembershipUser user0)
		{
			if( user0 == null )
			{
				if ( SecurityTraceSwitch.Sw.TraceError )
					Trace.WriteLine( string.Format(CultureInfo.InvariantCulture,"[E]AddonNiceMembershipProvider UpdateEmail Error portalID: {0}, user null.",PortalID),SecurityTraceSwitch.Sw.Info); 
				throw new ArgumentNullException( "user" );
			}
			if( !(user0 is AddonNiceMembershipUser ) )
			{
				if ( SecurityTraceSwitch.Sw.TraceError )
					Trace.WriteLine( string.Format(CultureInfo.InvariantCulture,"[E]AddonNiceMembershipProvider UpdateEmail Error portalID: {0}, user is not AddonNiceMembershipUser ",
						PortalID),SecurityTraceSwitch.Sw.Info); 
				throw new ProviderException( "Not CRMMembershipUser" );
			}

			AddonNiceMembershipUser user    = (AddonNiceMembershipUser) user0;
			if ( SecurityTraceSwitch.Sw.TraceVerbose )
				Trace.WriteLine( string.Format(CultureInfo.InvariantCulture,"[V]AddonNiceMembershipProvider UpdateEmail begin username: {0},user.typeName: {1},user.ProviderName: {2}",
					user.UserName,user.typeName,user.ProviderName),SecurityTraceSwitch.Sw.Info);

			string temp                     =   user.UserName;
			SecUtility.CheckParameter( ref temp, true, true, true, 256, "UserName" );
			temp                            =   user.CrmEMail;
			SecUtility.CheckParameter( ref temp,RequiresUniqueEmail,RequiresUniqueEmail,false,256,"Email");
			user.Email                      =   temp;
			
			try 
			{
				SqlConnectionHolder holder = null;
				try 
				{
					holder = SqlConnectionHelper.GetConnection( _sqlConnectionString, true );
					CheckSchemaVersion( holder.Connection );
					// no change from original proc
					SqlCommand    cmd     = new SqlCommand("dbo.AddonNice_Membership_UpdateEmail", holder.Connection);

					cmd.CommandTimeout = CommandTimeout;
					cmd.CommandType = CommandType.StoredProcedure;
					cmd.Parameters.Add(CreateInputParam("@ApplicationName", SqlDbType.NVarChar, ApplicationName));
					cmd.Parameters.Add(CreateInputParam("@UserName", SqlDbType.NVarChar, user.UserName));
					cmd.Parameters.Add(CreateInputParam("@Email", SqlDbType.NVarChar, user.Email));
					cmd.Parameters.Add(CreateInputParam("@CurrentTimeUtc", SqlDbType.DateTime, DateTime.UtcNow));

					SqlParameter p              =   new SqlParameter("@ReturnValue", SqlDbType.Int);
					p.Direction                 =   ParameterDirection.ReturnValue;
					cmd.Parameters.Add(p);
					cmd.ExecuteNonQuery();
					int status                  =   ((p.Value!=null) ? ((int) p.Value) : -1);
					if ( SecurityTraceSwitch.Sw.TraceVerbose )
						Trace.WriteLine( string.Format(CultureInfo.InvariantCulture,"[V]AddonNiceMembershipProvider UpdateEmail portalID: {0}, user.name: {1}, status: {2}",
							new object[] { PortalID, user.UserName,status}),SecurityTraceSwitch.Sw.Info); 
					if (status != 0)
						throw new ProviderException(GetExceptionText(status));
					return;
				}
				finally
				{
					if( holder != null )
					{
						holder.Close();
						holder = null;
					}
				}
			} 
			catch(Exception ex) 
			{
				if ( SecurityTraceSwitch.Sw.TraceError )
					Trace.WriteLine( string.Format(CultureInfo.InvariantCulture,"[E]AddonNiceMembershipProvider UpdateEmail portalID: {0}, user.name: {1}, ex: {2}",
						new object[] { PortalID, user.UserName,ex}),SecurityTraceSwitch.Sw.Info); 
				throw;
			}
		}


		#endregion Update user

		#region Check user

		public override bool ValidateUser(string username, string password)
		{
			if ( SecurityTraceSwitch.Sw.TraceVerbose )
				Trace.WriteLine( string.Format(CultureInfo.InvariantCulture,"[V]AddonNiceMembershipProvider ValidateUser BEG username: {0}, password: {1}.", username, password), SecurityTraceSwitch.Sw.Info);
			if (    SecUtility.ValidateParameter(ref username, true, true, true, 256) &&
					SecUtility.ValidateParameter(ref password, true, true, false, 128) &&
					CheckPassword(username, password, true, true))
			{
				if ( SecurityTraceSwitch.Sw.TraceVerbose )
					Trace.WriteLine( string.Format(CultureInfo.InvariantCulture,"[V]AddonNiceMembershipProvider ValidateUser END OK username: {0}",username),SecurityTraceSwitch.Sw.Info);
				// Comment out perf counters in sample: PerfCounters.IncrementCounter(AppPerfCounter.MEMBER_SUCCESS);
				// Comment out events in sample: WebBaseEvent.RaiseSystemEvent(null, WebEventCodes.AuditMembershipAuthenticationSuccess, username);
				return true;
			}
			if ( SecurityTraceSwitch.Sw.TraceVerbose )
				Trace.WriteLine( string.Format(CultureInfo.InvariantCulture,"[V]AddonNiceMembershipProvider ValidateUser END NOK username: {0}",username),SecurityTraceSwitch.Sw.Info);
			// Comment out perf counters in sample: PerfCounters.IncrementCounter(AppPerfCounter.MEMBER_FAIL);
			// Comment out events in sample: WebBaseEvent.RaiseSystemEvent(null, WebEventCodes.AuditMembershipAuthenticationFailure, username);
			return false;
		}

		public override bool UnlockUser( string username )
		{
			SecUtility.CheckParameter(ref username, true, true, true, 256, "username" );
			try 
			{
				SqlConnectionHolder holder = null;
				try 
				{
					holder = SqlConnectionHelper.GetConnection( _sqlConnectionString, true );
					CheckSchemaVersion(holder.Connection);

					SqlCommand cmd = new SqlCommand("dbo.AddonNice_Membership_UnlockUser", holder.Connection);

					cmd.CommandTimeout = CommandTimeout;
					cmd.CommandType = CommandType.StoredProcedure;
					cmd.Parameters.Add(CreateInputParam("@ApplicationName", SqlDbType.NVarChar, ApplicationName));
					cmd.Parameters.Add(CreateInputParam("@UserName", SqlDbType.NVarChar, username));

					SqlParameter p = new SqlParameter("@ReturnValue", SqlDbType.Int);
					p.Direction = ParameterDirection.ReturnValue;
					cmd.Parameters.Add(p);

					cmd.ExecuteNonQuery();

					int status = ((p.Value != null) ? ((int)p.Value) : -1);
					if (status == 0) 
					{
						return true;
					}

					return false;
				}
				finally {
					if( holder != null )
					{
						holder.Close();
						holder = null;
					}
				}
			} 
			catch(Exception ex) 
			{
				if ( SecurityTraceSwitch.Sw.TraceError )
					Trace.WriteLine( string.Format(CultureInfo.InvariantCulture,"[E]AddonNiceMembershipProvider UnlockUser Error portalID: {0}, ex: {1}",PortalID,ex),SecurityTraceSwitch.Sw.Info); 
				throw;
			}
		}

		#endregion Check user

		#region GetUser

		public override MembershipUser GetUser( object providerUserKey, bool userIsOnline )
		{
			if( providerUserKey == null )
			{
				if ( SecurityTraceSwitch.Sw.TraceError )
					Trace.WriteLine( string.Format(CultureInfo.InvariantCulture,"[E]AddonNiceMembershipProvider GetUser BEG portalID: {0}, providerUserKey is null",
						PortalID),SecurityTraceSwitch.Sw.Info); 
				throw new ArgumentNullException( "providerUserKey" );
			}
			if ( !( providerUserKey is Guid ) )
			{
				if ( SecurityTraceSwitch.Sw.TraceError )
					Trace.WriteLine( string.Format(CultureInfo.InvariantCulture,"[E]AddonNiceMembershipProvider GetUser BEG portalID: {0}, providerUserKey is not Guid: '{1}'",
						PortalID,providerUserKey.GetType()),SecurityTraceSwitch.Sw.Info); 
				throw new ArgumentException( SR.GetString( SR.Membership_InvalidProviderUserKey ), "providerUserKey" );
			}

			if ( SecurityTraceSwitch.Sw.TraceVerbose )
				Trace.WriteLine( string.Format(CultureInfo.InvariantCulture,"[V]AddonNiceMembershipProvider GetUser BEG portalID: {0}, providerUserKey: '{1}', userIsOnline: {2}",
						new object[] { PortalID, providerUserKey,userIsOnline}),SecurityTraceSwitch.Sw.Info); 
			AddonNiceMembershipUser user =   null;
			if ( Config.AuthenticationMode == AuthenticationMode.Forms )
					user    =   GetUserFromDB( providerUserKey, userIsOnline );
			else
			{
				user    =   GetUserFromCRM( providerUserKey, userIsOnline );
			}
			return user;
		}

		AddonNiceMembershipUser GetUserFromDB( object providerUserKey, bool userIsOnline )
		{
			if ( SecurityTraceSwitch.Sw.TraceVerbose )
				Trace.WriteLine( string.Format(CultureInfo.InvariantCulture,"[V]AddonNiceMembershipProvider GetUserFromDB BEG portalID: {0}, providerUserKey: '{1}', userIsOnline: {2}",
						new object[] { PortalID, providerUserKey,userIsOnline}),SecurityTraceSwitch.Sw.Info); 
			SqlDataReader       reader          =   null;
			try 
			{
				SqlConnectionHolder holder      =   null;
				try 
				{
					holder                      =   SqlConnectionHelper.GetConnection( _sqlConnectionString, true );
					CheckSchemaVersion( holder.Connection );

					SqlCommand    cmd           =   new SqlCommand( "dbo.AddonNice_Membership_GetUserByUserId", holder.Connection );

					cmd.CommandTimeout          =   CommandTimeout;
					cmd.CommandType             =   CommandType.StoredProcedure;
					cmd.Parameters.Add(CreateInputParam("@UserId", SqlDbType.UniqueIdentifier, providerUserKey ) );
					cmd.Parameters.Add(CreateInputParam("@UpdateLastActivity", SqlDbType.Bit, userIsOnline));
					cmd.Parameters.Add(CreateInputParam("@CurrentTimeUtc", SqlDbType.DateTime, DateTime.UtcNow));
					SqlParameter p                  =   new SqlParameter("@ReturnValue", SqlDbType.Int);
					p.Direction                     =   ParameterDirection.ReturnValue;
					cmd.Parameters.Add(p);

					reader                          =   cmd.ExecuteReader();
					if ( reader.Read() )
					{
						string email                =   GetNullableString(reader, 0);
						string passwordQuestion     =   GetNullableString( reader, 1 );
						string comment              =   GetNullableString(reader, 2);
						bool isApproved             =   reader.GetBoolean(3);
						DateTime dtCreate           =   reader.GetDateTime(4).ToLocalTime();
						DateTime dtLastLogin        =   reader.GetDateTime(5).ToLocalTime();
						DateTime dtLastActivity     =   reader.GetDateTime(6).ToLocalTime();
						DateTime dtLastPassChange   = reader.GetDateTime(7).ToLocalTime();
						string userName             =   GetNullableString(reader, 8);
						bool isLockedOut            =   reader.GetBoolean(9);
						DateTime dtLastLockoutDate  = reader.GetDateTime(10).ToLocalTime();
						// CS 7/8/7 Added to get CRM info
						int wCrmTypeCode            =   reader.GetInt32(11);
						Guid wCrmCustomerId         =   reader.GetGuid(12);
						Guid wCrmImpersonateId      =   reader.GetGuid(13);
						string wCrmImpersonateDomain=   reader.GetString(14);
						string wCrmImpersonateLogin =   reader.GetString(15);
						string EncodedCrmPwd        =   reader.GetString(16);
						string wCrmImpersonatePwd   =   UnEncodeCrmPassword(EncodedCrmPwd);
						bool wCrmIsCrmUser          =   reader.GetBoolean(17);
											   
						if ( SecurityTraceSwitch.Sw.TraceVerbose )
							Trace.WriteLine( string.Format(CultureInfo.InvariantCulture,"[V]AddonNiceMembershipProvider GetUserFromDB user found by providerUserKey in DB portalID: {0}, typeCode: {1}, wCrmCustomerId: {2}",
								new object[] { PortalID, wCrmTypeCode,wCrmCustomerId}),SecurityTraceSwitch.Sw.Info); 
						return new AddonNiceMembershipUser( this.Name,
												   userName,
												   providerUserKey,
												   new CrmCustomerId(wCrmTypeCode, wCrmCustomerId),
												   email,
												   passwordQuestion,
												   comment,
												   isApproved,
												   isLockedOut,
												   dtCreate,
												   dtLastLogin,
												   dtLastActivity,
												   dtLastPassChange,
												   dtLastLockoutDate,
												   PortalID,
												   ApplicationName,
												   wCrmImpersonateId,
												   wCrmImpersonateDomain,wCrmImpersonateLogin,wCrmImpersonatePwd,wCrmIsCrmUser
											   );
					}

					if ( SecurityTraceSwitch.Sw.TraceVerbose )
						Trace.WriteLine( string.Format(CultureInfo.InvariantCulture,"[V]AddonNiceMembershipProvider GetUserFromDB END user not found in DB portalID: {0}, providerUserKey: '{1}', userIsOnline: {2}",
								new object[] { PortalID, providerUserKey,userIsOnline}),SecurityTraceSwitch.Sw.Info); 
					return null;
				}
				finally
				{
					if ( reader != null )
					{
						reader.Close();
						reader = null;
					}

					if( holder != null )
					{
						holder.Close();
						holder = null;
					}
				}
			}
			catch(Exception ex) 
			{
				if ( SecurityTraceSwitch.Sw.TraceError )
					Trace.WriteLine( string.Format(CultureInfo.InvariantCulture,"[E]AddonNiceMembershipProvider GetUserFromDB Error portalID: {0}, ex: {1}",PortalID,ex),SecurityTraceSwitch.Sw.Info); 
				throw;
			}
		}

		/// <summary>
		/// Automatically add all relevant roles to User
		/// </summary>
		internal void CheckRoles(ADNDynSystemUser crmUser,AddonNiceMembershipUser muser)
		{
			bool RolesEnabled       =   Roles.Enabled;
			if ( SecurityTraceSwitch.Sw.TraceVerbose )
				Trace.WriteLine(string.Format(CultureInfo.InvariantCulture,"[V]AddonNiceMembershipProvider CheckRoles BEG UserName: {0}, RolesEnabled: {1}",muser.UserName,RolesEnabled),SecurityTraceSwitch.Sw.Info);
			if ( RolesEnabled )
			{
				string[] userRoles  =   Wrapper.GetStrUserRoles(crmUser.systemuserid);
				foreach ( string role in userRoles )
				{
					if ( SecurityTraceSwitch.Sw.TraceVerbose )
						Trace.WriteLine(string.Format(CultureInfo.InvariantCulture,"[V]AddonNiceMembershipProvider CheckRoles role : {0}",role),SecurityTraceSwitch.Sw.Info);
					if ( !Roles.RoleExists(role) )
					{
						if ( SecurityTraceSwitch.Sw.TraceVerbose )
							Trace.WriteLine(string.Format(CultureInfo.InvariantCulture,"[V]AddonNiceMembershipProvider CheckRoles adding role : {0}",role),SecurityTraceSwitch.Sw.Info);
						Roles.CreateRole(role);
					}
					if ( !Roles.IsUserInRole(muser.UserName,role) )
						Roles.AddUserToRole(muser.UserName,role);
				}
			}
			if ( SecurityTraceSwitch.Sw.TraceVerbose )
				Trace.WriteLine("[V]AddonNiceMembershipProvider CheckRoles END.",SecurityTraceSwitch.Sw.Info);
		}

		/// <summary>
		/// If user not in DB and in CRM, create it in DB from CRM values
		/// </summary>
		AddonNiceMembershipUser GetUserFromCRM( object providerUserKey, bool userIsOnline )
		{
			if ( SecurityTraceSwitch.Sw.TraceVerbose )
				Trace.WriteLine( string.Format(CultureInfo.InvariantCulture,"[V]AddonNiceMembershipProvider GetUserFromCRM BEG portalID: {0}, providerUserKey: '{1}', userIsOnline: {2}",
						new object[] { PortalID, providerUserKey,userIsOnline}),SecurityTraceSwitch.Sw.Info); 
			AddonNiceMembershipUser muser   =   GetUserFromDB( providerUserKey, userIsOnline );
			if ( muser != null )
				return muser;
			try 
			{
				ADNDynSystemUser crmUser    =   DynEntity.GetFromCache<ADNDynSystemUser>(CrmStr.systemuser,Wrapper,new ResetWrapperHandler(ResetWrapper),(Guid)providerUserKey);
				if ( crmUser.Retrieved )
				{
					muser                   =   (AddonNiceMembershipUser)CreateFromCrmUser(crmUser);
					if ( SecurityTraceSwitch.Sw.TraceVerbose )
						Trace.WriteLine( string.Format(CultureInfo.InvariantCulture,"[V]AddonNiceMembershipProvider GetUserFromCRM END user not found in DB created: {0}, providerUserKey: '{1}', userIsOnline: {2}",
								new object[] { (muser != null), providerUserKey,userIsOnline}),SecurityTraceSwitch.Sw.Info); 
					//CheckRoles(crmUser,muser);
				}
			}
			catch(Exception ex) 
			{
				if ( SecurityTraceSwitch.Sw.TraceError )
					Trace.WriteLine( string.Format(CultureInfo.InvariantCulture,"[E]AddonNiceMembershipProvider GetUserFromCRM Error portalID: {0}, ex: {1}",PortalID,ex),SecurityTraceSwitch.Sw.Info); 
				throw;
			}
			return muser;
		}

		public override MembershipUser GetUser(string username, bool userIsOnline)
		{
			if ( SecurityTraceSwitch.Sw.TraceVerbose )
				Trace.WriteLine( string.Format(CultureInfo.InvariantCulture,"[V]AddonNiceMembershipProvider GetUser BEG portalID: {0}, username: '{1}', userIsOnline: {2}",
						new object[] { PortalID, username, userIsOnline}),SecurityTraceSwitch.Sw.Info); 
			SecUtility.CheckParameter(ref username,true,false,true,256,"username" );
			AddonNiceMembershipUser user =   null;
			if ( username == string.Empty )
				return user;
			if ( Config.AuthenticationMode == AuthenticationMode.Forms )
					user    =   GetUserFromDB( username, userIsOnline );
			else
			{
				user        =   GetUserFromCRM( username, userIsOnline );
			}
			return user;
		}

		AddonNiceMembershipUser GetUserFromDB(string username, bool userIsOnline)
		{
			if ( SecurityTraceSwitch.Sw.TraceVerbose )
				Trace.WriteLine( string.Format(CultureInfo.InvariantCulture,"[V]AddonNiceMembershipProvider GetUserFromDB BEG portalID: {0}, username: '{1}', userIsOnline: {2}, ApplicationName: {3}",
						new object[] { PortalID, username, userIsOnline,ApplicationName}),SecurityTraceSwitch.Sw.Info); 
			if ( username == string.Empty )
				return null;
			SqlDataReader        reader         =   null;

			try 
			{
				SqlConnectionHolder holder      =   null;
				try 
				{
					holder                      =   SqlConnectionHelper.GetConnection( _sqlConnectionString, true );
					CheckSchemaVersion( holder.Connection );

					SqlCommand    cmd           =   new SqlCommand("dbo.AddonNice_Membership_GetUserByName", holder.Connection);

					cmd.CommandTimeout          =   CommandTimeout;
					cmd.CommandType             =   CommandType.StoredProcedure;
					cmd.Parameters.Add(CreateInputParam("@ApplicationName", SqlDbType.NVarChar, ApplicationName));
					cmd.Parameters.Add(CreateInputParam("@UserName", SqlDbType.NVarChar, username));
					cmd.Parameters.Add(CreateInputParam("@UpdateLastActivity", SqlDbType.Bit, userIsOnline));
					cmd.Parameters.Add(CreateInputParam("@CurrentTimeUtc", SqlDbType.DateTime, DateTime.UtcNow));
					SqlParameter p              =   new SqlParameter("@ReturnValue", SqlDbType.Int);
					p.Direction                 =   ParameterDirection.ReturnValue;
					cmd.Parameters.Add(p);

					reader                      =   cmd.ExecuteReader();
					if ( reader.Read() )
					{
						string email            =   GetNullableString(reader, 0);
						string passwordQuestion =   GetNullableString( reader, 1 );
						string comment          =   GetNullableString(reader, 2);
						bool isApproved         =   reader.GetBoolean(3);
						DateTime dtCreate       =   reader.GetDateTime(4).ToLocalTime();
						DateTime dtLastLogin    =   reader.GetDateTime(5).ToLocalTime();
						DateTime dtLastActivity =   reader.GetDateTime(6).ToLocalTime();
						DateTime dtLastPassChange = reader.GetDateTime(7).ToLocalTime();
						Guid userId             =   reader.GetGuid( 8 );
						bool isLockedOut        =   reader.GetBoolean( 9 );
						DateTime dtLastLockoutDate = reader.GetDateTime(10).ToLocalTime();

						// CS 7/8/7 Added to get CRM info
						int wCrmTypeCode            =   reader.GetInt32(11);
						Guid wCrmCustomerId         =   reader.GetGuid(12);
						Guid wCrmImpersonateId      =   reader.GetGuid(13);
						string wCrmImpersonateDomain=   reader.GetString(14);
						string wCrmImpersonateLogin =   reader.GetString(15);
						string EncodedCrmPwd        =   reader.GetString(16);
						string wCrmImpersonatePwd   =   UnEncodeCrmPassword(EncodedCrmPwd);
						bool wCrmIsCrmUser          =   reader.GetBoolean(17);

						if ( SecurityTraceSwitch.Sw.TraceVerbose )
							Trace.WriteLine( string.Format(CultureInfo.InvariantCulture,"[V]AddonNiceMembershipProvider GetUserFromDB user found by name in DB portalID: {0}, typeCode: {1}, wCrmCustomerId: {2}",
								new object[] { PortalID, wCrmTypeCode,wCrmCustomerId}),SecurityTraceSwitch.Sw.Info); 
						return new AddonNiceMembershipUser( this.Name,
												   username,
												   userId,
												   new CrmCustomerId(wCrmTypeCode, wCrmCustomerId),
												   email,
												   passwordQuestion,
												   comment,
												   isApproved,
												   isLockedOut,
												   dtCreate,
												   dtLastLogin,
												   dtLastActivity,
												   dtLastPassChange,
												   dtLastLockoutDate,
												   PortalID,
												   ApplicationName,
												   wCrmImpersonateId,
												   wCrmImpersonateDomain,wCrmImpersonateLogin,wCrmImpersonatePwd,wCrmIsCrmUser);
					}

					if ( SecurityTraceSwitch.Sw.TraceVerbose )
						Trace.WriteLine( string.Format(CultureInfo.InvariantCulture,"[V]AddonNiceMembershipProvider GetUserFromDB END Not Found returning null portalID: {0}, username: {1}, userIsOnline: {2}, not found",
							new object[] { PortalID, username, userIsOnline}),SecurityTraceSwitch.Sw.Info); 
					return null;

				}
				finally
				{
					if ( reader != null )
					{
						reader.Close();
						reader = null;
					}

					if( holder != null )
					{
						holder.Close();
						holder = null;
					}
				}
			}
			catch(Exception ex)
			{
				if ( SecurityTraceSwitch.Sw.TraceError )
					Trace.WriteLine( string.Format(CultureInfo.InvariantCulture,"[E]AddonNiceMembershipProvider GetUserFromDB  portalID: {0}, username: {1}, userIsOnline: {2}, ex: {3}",
						new object[] { PortalID, username, userIsOnline,ex}),SecurityTraceSwitch.Sw.Info); 
				throw;
			}
		}

		/// <summary>
		/// If user not in DB and in CRM, create it in DB from CRM values
		/// Normally called only in windows authentication
		/// </summary>
		AddonNiceMembershipUser GetUserFromCRM( string username, bool userIsOnline)
		{
			if ( SecurityTraceSwitch.Sw.TraceVerbose )
				Trace.WriteLine( string.Format(CultureInfo.InvariantCulture,"[V]AddonNiceMembershipProvider GetUserFromCRM BEG portalID: {0}, username: '{1}', userIsOnline: {2}",
						new object[] { PortalID, username, userIsOnline}),SecurityTraceSwitch.Sw.Info); 
			AddonNiceMembershipUser muser   =   GetUserFromDB( username, userIsOnline );
			if ( muser != null )
				return muser;
			try 
			{
				ADNDynSystemUser crmUser    =   Wrapper.Util.FindSystemUserByDomainName(username,true);
				if ( crmUser != null )
				{
					muser                   =   (AddonNiceMembershipUser)CreateFromCrmUser(crmUser);
					if ( SecurityTraceSwitch.Sw.TraceVerbose )
						Trace.WriteLine( string.Format(CultureInfo.InvariantCulture,"[V]AddonNiceMembershipProvider GetUserFromCRM END user not found in DB created: {0}, username: '{1}', userIsOnline: {2}",
								new object[] { (muser != null), username,userIsOnline}),SecurityTraceSwitch.Sw.Info); 
					//CheckRoles(crmUser,muser);
				}
			}
			catch(Exception ex) 
			{
				if ( SecurityTraceSwitch.Sw.TraceError )
					Trace.WriteLine( string.Format(CultureInfo.InvariantCulture,"[E]AddonNiceMembershipProvider GetUserFromCRM Error portalID: {0}, ex: {1}",PortalID,ex),SecurityTraceSwitch.Sw.Info); 
				throw;
			}
			return muser;
		}

		public override string GetUserNameByEmail(string email)
		{
			if ( SecurityTraceSwitch.Sw.TraceVerbose )
				Trace.WriteLine( string.Format(CultureInfo.InvariantCulture,"[V]AddonNiceMembershipProvider GetUserNameByEmail BEG portalID: {0}, email: {1}",
						PortalID, email),SecurityTraceSwitch.Sw.Info); 
			SecUtility.CheckParameter(ref email,false,false,false,256,"email" );
			string userName =   null;
			if ( Config.AuthenticationMode == AuthenticationMode.Forms )
				userName    =   GetUserNameByEmailFromDB( email );
			else
			{
				userName    =   GetUserNameByEmailFromCRM( email );
			}
			return userName;
		}        
		
		string GetUserNameByEmailFromDB(string email)
		{
			if ( SecurityTraceSwitch.Sw.TraceVerbose )
				Trace.WriteLine( string.Format(CultureInfo.InvariantCulture,"[V]AddonNiceMembershipProvider GetUserNameByEmailFromDB BEG portalID: {0}, email: '{1}'",
						PortalID, email),SecurityTraceSwitch.Sw.Info); 
			try 
			{
				if ( email == string.Empty )
					return null;
				SqlConnectionHolder holder      =   null;
				try 
				{
					holder                      =   SqlConnectionHelper.GetConnection(_sqlConnectionString, true);
					CheckSchemaVersion( holder.Connection );

					SqlCommand    cmd           =   new SqlCommand("dbo.AddonNice_Membership_GetUserByEmail", holder.Connection);
					string        username      =   null;
					SqlDataReader reader        =   null;

					cmd.CommandTimeout          =   CommandTimeout;
					cmd.CommandType             =   CommandType.StoredProcedure;
					cmd.Parameters.Add(CreateInputParam("@ApplicationName", SqlDbType.NVarChar, ApplicationName));
					cmd.Parameters.Add(CreateInputParam("@Email", SqlDbType.NVarChar, email));

					SqlParameter p              =   new SqlParameter("@ReturnValue", SqlDbType.Int);
					p.Direction                 =   ParameterDirection.ReturnValue;
					cmd.Parameters.Add(p);
					try 
					{
						reader                  =   cmd.ExecuteReader(CommandBehavior.SequentialAccess);
						if (reader.Read())
						{
							username            =   GetNullableString( reader, 0 );
							if ( RequiresUniqueEmail && reader.Read() )
							{
								if ( SecurityTraceSwitch.Sw.TraceError )
									Trace.WriteLine( string.Format(CultureInfo.InvariantCulture,"[E]AddonNiceMembershipProvider GetUserNameByEmailFromDB BEG portalID: {0}, email: {1}, RequiresUniqueEmail and more than one email found",
										PortalID, email),SecurityTraceSwitch.Sw.Info); 
								throw new ProviderException(SR.GetString(SR.Membership_more_than_one_user_with_email));
							}
						}
					}
					finally
					{
						if (reader != null)
							reader.Close();
					}
					if ( SecurityTraceSwitch.Sw.TraceVerbose )
						Trace.WriteLine( string.Format(CultureInfo.InvariantCulture,"[V]AddonNiceMembershipProvider GetUserNameByEmailFromDB END portalID: {0}, email: {1}, found username: {2}",
							PortalID, email,username),SecurityTraceSwitch.Sw.Info); 
					return username;
				}
				finally
				{
					if( holder != null )
					{
						holder.Close();
						holder = null;
					}
				}
			} 
			catch (Exception ex)
			{
				if ( SecurityTraceSwitch.Sw.TraceError )
					Trace.WriteLine( string.Format(CultureInfo.InvariantCulture,"[E]AddonNiceMembershipProvider GetUserNameByEmailFromDB Error portalID: {0}, email: {1}, ex: {2}",
						PortalID, email,ex),SecurityTraceSwitch.Sw.Info); 
				throw;
			}
		}

		/// <summary>
		/// If user not in DB and in CRM, create it in DB from CRM values
		/// </summary>
		string GetUserNameByEmailFromCRM(string email)
		{
			if ( SecurityTraceSwitch.Sw.TraceVerbose )
				Trace.WriteLine( string.Format(CultureInfo.InvariantCulture,"[V]AddonNiceMembershipProvider GetUserNameByEmailFromCRM BEG portalID: {0}, email: '{1}'",
						PortalID, email),SecurityTraceSwitch.Sw.Info); 
			if ( email == string.Empty )
				return null;
			string userName                     =   GetUserNameByEmailFromDB( email );
			if ( userName != null )
				return userName;
			AddonNiceMembershipUser muser       =   null;
			try 
			{
				int cntf                        =   0;
				ADNDynSystemUser crmUser        =   Wrapper.Util.FindEntityByStringField<ADNDynSystemUser>(CrmStr.systemuser,CrmStr.internalemailaddress ,email,ResetWrapper,ref cntf,false,null);
				if ( crmUser != null )
				{
					muser                       =   (AddonNiceMembershipUser)CreateFromCrmUser(crmUser);
					if ( SecurityTraceSwitch.Sw.TraceVerbose )
						Trace.WriteLine( string.Format(CultureInfo.InvariantCulture,"[V]AddonNiceMembershipProvider GetUserNameByEmailFromCRM END user not found in DB created: {0}, email: '{1}', count: {2}",
								new object[] { (muser != null), email,cntf}),SecurityTraceSwitch.Sw.Info); 
					//CheckRoles(crmUser,muser);
				}
			}
			catch(Exception ex) 
			{
				if ( SecurityTraceSwitch.Sw.TraceError )
					Trace.WriteLine( string.Format(CultureInfo.InvariantCulture,"[E]AddonNiceMembershipProvider GetUserFromCRM Error portalID: {0}, ex: {1}",PortalID,ex),SecurityTraceSwitch.Sw.Info); 
				throw;
			}
			return (muser == null ) ? null:muser.UserName;
		}


		public override MembershipUserCollection GetAllUsers(int pageIndex, int pageSize, out int totalRecords)
		{
			if ( SecurityTraceSwitch.Sw.TraceVerbose )
				Trace.WriteLine( string.Format(CultureInfo.InvariantCulture,"[V]AddonNiceMembershipProvider GetAllUsers BEG portalID: {0}, pageIndex: {1}, pageSize: {2}",
							PortalID, pageIndex,pageSize),SecurityTraceSwitch.Sw.Info); 
			if ( pageIndex < 0 )
				throw new ArgumentException(SR.GetString(SR.PageIndex_bad), "pageIndex");
			if ( pageSize < 1 )
				throw new ArgumentException(SR.GetString(SR.PageSize_bad), "pageSize");

			long upperBound                 =   (long)pageIndex * pageSize + pageSize - 1;
			if ( upperBound > Int32.MaxValue )
				throw new ArgumentException(SR.GetString(SR.PageIndex_PageSize_bad), "pageIndex and pageSize");

			MembershipUserCollection users  =   new MembershipUserCollection();
			totalRecords                    =   0;
			try 
			{
				SqlConnectionHolder holder  =   null;
				try 
				{
					holder                  =   SqlConnectionHelper.GetConnection(_sqlConnectionString, true);
					CheckSchemaVersion( holder.Connection );

					SqlCommand cmd          =   new SqlCommand("dbo.AddonNice_Membership_GetAllUsers", holder.Connection);
					SqlDataReader reader    =   null;
					SqlParameter p          =   new SqlParameter("@ReturnValue", SqlDbType.Int);

					cmd.CommandTimeout      =   CommandTimeout;
					cmd.CommandType         =   CommandType.StoredProcedure;
					cmd.Parameters.Add(CreateInputParam("@ApplicationName", SqlDbType.NVarChar, ApplicationName));
					cmd.Parameters.Add(CreateInputParam("@PageIndex", SqlDbType.Int, pageIndex));
					cmd.Parameters.Add(CreateInputParam("@PageSize", SqlDbType.Int, pageSize));
					p.Direction             =   ParameterDirection.ReturnValue;
					cmd.Parameters.Add(p);
					try 
					{
						reader              =   cmd.ExecuteReader(CommandBehavior.SequentialAccess);
						while (reader.Read()) 
						{
							string username             =   GetNullableString( reader, 0 );
							string email                =   GetNullableString(reader, 1);
							string passwordQuestion     =   GetNullableString( reader, 2 );
							string comment              =   GetNullableString(reader, 3);
							bool isApproved             =   reader.GetBoolean(4);
							DateTime dtCreate           =   reader.GetDateTime(5).ToLocalTime();
							DateTime dtLastLogin        =   reader.GetDateTime(6).ToLocalTime();
							DateTime dtLastActivity     =   reader.GetDateTime(7).ToLocalTime();
							DateTime dtLastPassChange   =   reader.GetDateTime(8).ToLocalTime();
							Guid userId                 =   reader.GetGuid( 9 );
							bool isLockedOut            =   reader.GetBoolean( 10 );
							DateTime dtLastLockoutDate  =   reader.GetDateTime(11).ToLocalTime();
							// CS 7/8/7 Added to get CRM info
							int wCrmTypeCode            =   reader.GetInt32(12);
							Guid wCrmCustomerId         =   reader.GetGuid(13);
							Guid wCrmImpersonateId      =   reader.GetGuid(14);
							string wCrmImpersonateDomain=   reader.GetString(15);
							string wCrmImpersonateLogin =   reader.GetString(16);
							string EncodedCrmPwd        =   reader.GetString(17);
							string wCrmImpersonatePwd   =   UnEncodeCrmPassword(EncodedCrmPwd);
							bool wCrmIsCrmUser          =   reader.GetBoolean(18);
							
							if (SecurityTraceSwitch.Sw.TraceVerbose)
								Trace.WriteLine( string.Format(CultureInfo.InvariantCulture,"[V]AddonNiceMembershipProvider GetAllUsers Adding portalID: {0}, typeCode: {1}, username: {2}",
									new object[] { PortalID, wCrmTypeCode,username}),SecurityTraceSwitch.Sw.Info); 
							users.Add( new AddonNiceMembershipUser( this.Name,
														   username,
														   userId,
														   new CrmCustomerId(wCrmTypeCode, wCrmCustomerId),
														   email,
														   passwordQuestion,
														   comment,
														   isApproved,
														   isLockedOut,
														   dtCreate,
														   dtLastLogin,
														   dtLastActivity,
														   dtLastPassChange,
														   dtLastLockoutDate,
														   PortalID,
														   ApplicationName,
														   wCrmImpersonateId,
														   wCrmImpersonateDomain,wCrmImpersonateLogin,wCrmImpersonatePwd,wCrmIsCrmUser)
														   );
						}
					}
					finally
					{
						if (reader != null)
							reader.Close();
						if (p.Value != null && p.Value is int)
							totalRecords = (int)p.Value;
					}
				}
				finally
				{
					if( holder != null )
					{
						holder.Close();
						holder = null;
					}
				}
			} 
			catch (Exception ex)
			{
				if ( SecurityTraceSwitch.Sw.TraceError )
					Trace.WriteLine( string.Format(CultureInfo.InvariantCulture,"[E]AddonNiceMembershipProvider GetAllUsers Error portalID: {0}, pageIndex: {1}, pageSize: {2}, totalRecords: {3}, ex: {4}",
						new object[] { PortalID,pageIndex,pageSize,totalRecords,ex}),SecurityTraceSwitch.Sw.Info); 
				throw;
			}
			if ( SecurityTraceSwitch.Sw.TraceVerbose )
				Trace.WriteLine( string.Format(CultureInfo.InvariantCulture,"[V]AddonNiceMembershipProvider GetAllUsers END portalID: {0}, pageIndex: {1}, pageSize: {2}, totalRecords: {3}, users.Count: {4}",
					new object[] { PortalID,pageIndex,pageSize,totalRecords,users.Count}),SecurityTraceSwitch.Sw.Info); 
			return users;
		}

		public override int GetNumberOfUsersOnline()
		{
			try 
			{
				SqlConnectionHolder holder  =    null;
				try 
				{
					holder                  =   SqlConnectionHelper.GetConnection(_sqlConnectionString, true);
					CheckSchemaVersion( holder.Connection );

					SqlCommand    cmd       =   new SqlCommand("dbo.AddonNice_Membership_GetNumberOfUsersOnline", holder.Connection);
					SqlParameter  p         =   new SqlParameter("@ReturnValue", SqlDbType.Int);

					cmd.CommandTimeout      =   CommandTimeout;
					cmd.CommandType         =   CommandType.StoredProcedure;
					cmd.Parameters.Add(CreateInputParam("@ApplicationName", SqlDbType.NVarChar, ApplicationName));
					cmd.Parameters.Add(CreateInputParam("@MinutesSinceLastInActive", SqlDbType.Int, Membership.UserIsOnlineTimeWindow));
					cmd.Parameters.Add(CreateInputParam("@CurrentTimeUtc", SqlDbType.DateTime, DateTime.UtcNow));
					p.Direction             =   ParameterDirection.ReturnValue;
					cmd.Parameters.Add(p);
					cmd.ExecuteNonQuery();
					int num                 =   ((p.Value!=null) ? ((int) p.Value) : -1);
					return num;
				}
				finally
				{
					if( holder != null )
					{
						holder.Close();
						holder              =   null;
					}
				}
			} 
			catch 
			{
				throw;
			}
		}

		public override MembershipUserCollection FindUsersByName(string usernameToMatch, int pageIndex, int pageSize, out int totalRecords)
		{
			SecUtility.CheckParameter(ref usernameToMatch, true, true, false, 256, "usernameToMatch");

			if ( pageIndex < 0 )
				throw new ArgumentException(SR.GetString(SR.PageIndex_bad), "pageIndex");
			if ( pageSize < 1 )
				throw new ArgumentException(SR.GetString(SR.PageSize_bad), "pageSize");

			long upperBound = (long)pageIndex * pageSize + pageSize - 1;
			if ( upperBound > Int32.MaxValue )
				throw new ArgumentException(SR.GetString(SR.PageIndex_PageSize_bad), "pageIndex and pageSize");

			try
			{
				SqlConnectionHolder holder          =   null;
				totalRecords                        =   0;
				SqlParameter p                      =   new SqlParameter("@ReturnValue", SqlDbType.Int);
				p.Direction                         =   ParameterDirection.ReturnValue;
				try 
				{
					holder                          =   SqlConnectionHelper.GetConnection(_sqlConnectionString, true);
					CheckSchemaVersion( holder.Connection );

					SqlCommand cmd                  =   new SqlCommand("dbo.AddonNice_Membership_FindUsersByName", holder.Connection);
					MembershipUserCollection users  =   new MembershipUserCollection();
					SqlDataReader reader            =   null;

					cmd.CommandTimeout              =   CommandTimeout;
					cmd.CommandType                 =   CommandType.StoredProcedure;
					cmd.Parameters.Add(CreateInputParam("@ApplicationName", SqlDbType.NVarChar, ApplicationName));
					cmd.Parameters.Add(CreateInputParam("@UserNameToMatch", SqlDbType.NVarChar, usernameToMatch));
					cmd.Parameters.Add(CreateInputParam("@PageIndex", SqlDbType.Int, pageIndex));
					cmd.Parameters.Add(CreateInputParam("@PageSize", SqlDbType.Int, pageSize));
					cmd.Parameters.Add(p);
					try
					{
						reader                      =    cmd.ExecuteReader(CommandBehavior.SequentialAccess);
						while (reader.Read())
						{
							string username, email, passwordQuestion, comment;
							bool isApproved;
							DateTime dtCreate, dtLastLogin, dtLastActivity, dtLastPassChange;
							Guid userId;
							bool isLockedOut;
							DateTime dtLastLockoutDate;

							username                =   GetNullableString( reader, 0 );
							email                   =   GetNullableString(reader, 1);
							passwordQuestion        =   GetNullableString( reader, 2 );
							comment                 =   GetNullableString(reader, 3);
							isApproved              =   reader.GetBoolean(4);
							dtCreate                =   reader.GetDateTime(5).ToLocalTime();
							dtLastLogin             =   reader.GetDateTime(6).ToLocalTime();
							dtLastActivity          =   reader.GetDateTime(7).ToLocalTime();
							dtLastPassChange        =   reader.GetDateTime(8).ToLocalTime();
							userId                  =   reader.GetGuid( 9 );
							isLockedOut             =   reader.GetBoolean( 10 );
							dtLastLockoutDate       =   reader.GetDateTime(11).ToLocalTime();
							// CS 7/8/7 Added to get CRM info
							int wCrmTypeCode            =   reader.GetInt32(12);
							Guid wCrmCustomerId         =   reader.GetGuid(13);
							Guid wCrmImpersonateId      =   reader.GetGuid(14);
							string wCrmImpersonateDomain=   reader.GetString(14);
							string wCrmImpersonateLogin =   reader.GetString(15);
							string EncodedCrmPwd        =   reader.GetString(16);
							string wCrmImpersonatePwd   =   UnEncodeCrmPassword(EncodedCrmPwd);
							bool wCrmIsCrmUser          =   reader.GetBoolean(17);

							users.Add( new AddonNiceMembershipUser( this.Name,
														   username,
														   userId,
														   new CrmCustomerId(wCrmTypeCode, wCrmCustomerId),
														   email,
														   passwordQuestion,
														   comment,
														   isApproved,
														   isLockedOut,
														   dtCreate,
														   dtLastLogin,
														   dtLastActivity,
														   dtLastPassChange,
														   dtLastLockoutDate,
														   PortalID,
														   ApplicationName,
														   wCrmImpersonateId,
														   wCrmImpersonateDomain,wCrmImpersonateLogin,wCrmImpersonatePwd,wCrmIsCrmUser)
														   );
						}

						return users;
					}
					finally
					{
						if (reader != null)
							reader.Close();
						if (p.Value != null && (p.Value is int))
							totalRecords            =   (int) p.Value;
					}
				}
				finally
				{
					if( holder != null )
					{
						holder.Close();
						holder                      =   null;
					}
				}
			} catch {
				throw;
			}
		}

		public override MembershipUserCollection FindUsersByEmail(string emailToMatch, int pageIndex, int pageSize, out int totalRecords)
		{
			SecUtility.CheckParameter(ref emailToMatch, false, false, false, 256, "emailToMatch");

			if ( pageIndex < 0 )
				throw new ArgumentException(SR.GetString(SR.PageIndex_bad), "pageIndex");
			if ( pageSize < 1 )
				throw new ArgumentException(SR.GetString(SR.PageSize_bad), "pageSize");

			long upperBound = (long)pageIndex * pageSize + pageSize - 1;
			if ( upperBound > Int32.MaxValue )
				throw new ArgumentException(SR.GetString(SR.PageIndex_PageSize_bad), "pageIndex and pageSize");

			try 
			{
				SqlConnectionHolder holder              =   null;
				totalRecords                            =   0;
				SqlParameter p                          =   new SqlParameter("@ReturnValue", SqlDbType.Int);
				p.Direction                             =   ParameterDirection.ReturnValue;
				try 
				{
					holder = SqlConnectionHelper.GetConnection(_sqlConnectionString, true);
					CheckSchemaVersion( holder.Connection );

					SqlCommand cmd                      =   new SqlCommand("dbo.AddonNice_Membership_FindUsersByEmail", holder.Connection);
					MembershipUserCollection users      =   new MembershipUserCollection();
					SqlDataReader reader                =   null;

					cmd.CommandTimeout = CommandTimeout;
					cmd.CommandType = CommandType.StoredProcedure;
					cmd.Parameters.Add(CreateInputParam("@ApplicationName", SqlDbType.NVarChar, ApplicationName));
					cmd.Parameters.Add(CreateInputParam("@EmailToMatch", SqlDbType.NVarChar, emailToMatch));
					cmd.Parameters.Add(CreateInputParam("@PageIndex", SqlDbType.Int, pageIndex));
					cmd.Parameters.Add(CreateInputParam("@PageSize", SqlDbType.Int, pageSize));
					cmd.Parameters.Add(p);
					try 
					{
						reader = cmd.ExecuteReader(CommandBehavior.SequentialAccess);
						while (reader.Read()) 
						{
							string username, email, passwordQuestion, comment;
							bool isApproved;
							DateTime dtCreate, dtLastLogin, dtLastActivity, dtLastPassChange;
							Guid userId;
							bool isLockedOut;
							DateTime dtLastLockoutDate;

							username                    =   GetNullableString( reader, 0 );
							email                       =   GetNullableString(reader, 1);
							passwordQuestion            =   GetNullableString( reader, 2 );
							comment                     =   GetNullableString(reader, 3);
							isApproved                  =   reader.GetBoolean(4);
							dtCreate                    =   reader.GetDateTime(5).ToLocalTime();
							dtLastLogin                 =   reader.GetDateTime(6).ToLocalTime();
							dtLastActivity              =   reader.GetDateTime(7).ToLocalTime();
							dtLastPassChange            =   reader.GetDateTime(8).ToLocalTime();
							userId                      =   reader.GetGuid( 9 );
							isLockedOut                 =   reader.GetBoolean( 10 );
							dtLastLockoutDate           =   reader.GetDateTime(11).ToLocalTime();
							// CS 7/8/7 Added to get CRM info
							int wCrmTypeCode            =   reader.GetInt32(12);
							Guid wCrmCustomerId         =   reader.GetGuid(13);
							Guid wCrmImpersonateId      =   reader.GetGuid(14);
							string wCrmImpersonateDomain=   reader.GetString(14);
							string wCrmImpersonateLogin =   reader.GetString(15);
							string EncodedCrmPwd        =   reader.GetString(16);
							string wCrmImpersonatePwd   =   UnEncodeCrmPassword(EncodedCrmPwd);
							bool wCrmIsCrmUser          =   reader.GetBoolean(17);

							users.Add( new AddonNiceMembershipUser( this.Name,
														   username,
														   userId,
														   new CrmCustomerId(wCrmTypeCode, wCrmCustomerId),
														   email,
														   passwordQuestion,
														   comment,
														   isApproved,
														   isLockedOut,
														   dtCreate,
														   dtLastLogin,
														   dtLastActivity,
														   dtLastPassChange,
														   dtLastLockoutDate,
														   PortalID,
														   ApplicationName,
														   wCrmImpersonateId,
														   wCrmImpersonateDomain,wCrmImpersonateLogin,wCrmImpersonatePwd,wCrmIsCrmUser)
														   );
						}

						return users;
					}
					finally
					{
						if (reader != null)
							reader.Close();
						if (p.Value != null && ( p.Value is int) )
							totalRecords    =   (int)p.Value;
					}
				}
				finally
				{
					if( holder != null )
					{
						holder.Close();
						holder              =   null;
					}
				}
			} catch {
				throw;
			}
		}

		#endregion GetUser

		#region Delete User

		public override bool DeleteUser(string username, bool deleteAllRelatedData)
		{
			if ( SecurityTraceSwitch.Sw.TraceVerbose )
				Trace.WriteLine( string.Format(CultureInfo.InvariantCulture,"[V]AddonNiceMembershipProvider DeleteUser BEG portalID: {0}, username: {1}, deleteAllRelatedData: {2}",
						PortalID, username,deleteAllRelatedData),SecurityTraceSwitch.Sw.Info); 
			SecUtility.CheckParameter( ref username, true, true, true, 256, "username" );

			try 
			{
				SqlConnectionHolder holder              =   null;
				try 
				{
					holder                              =   SqlConnectionHelper.GetConnection(_sqlConnectionString, true);
					CheckSchemaVersion( holder.Connection );
					SqlCommand cmd                      =   new SqlCommand("dbo.AddonNice_Users_DeleteUser", holder.Connection);

					cmd.CommandTimeout                  =   CommandTimeout;
					cmd.CommandType                     =   CommandType.StoredProcedure;
					cmd.Parameters.Add(CreateInputParam("@ApplicationName", SqlDbType.NVarChar, ApplicationName));
					cmd.Parameters.Add(CreateInputParam("@UserName", SqlDbType.NVarChar, username));

					if( deleteAllRelatedData )
					{
						cmd.Parameters.Add(CreateInputParam("@TablesToDeleteFrom", SqlDbType.Int, 0xF));
					}
					else
					{
						cmd.Parameters.Add(CreateInputParam("@TablesToDeleteFrom", SqlDbType.Int, 1));
					}

					SqlParameter p                      =   new SqlParameter("@NumTablesDeletedFrom", SqlDbType.Int);
					p.Direction                         =   ParameterDirection.Output;
					cmd.Parameters.Add(p);
					cmd.ExecuteNonQuery();

					int status = ( ( p.Value != null ) ? ( ( int )p.Value ) : -1 );

					return ( status > 0 );
				}
				finally
				{
					if( holder != null )
					{
						holder.Close();
						holder = null;
					}
				}
			} 
			catch (Exception ex)
			{
				if ( SecurityTraceSwitch.Sw.TraceError)
					Trace.WriteLine( string.Format(CultureInfo.InvariantCulture,"[E]AddonNiceMembershipProvider DeleteUser Error portalID: {0}, username: {1}, ex: {2}",
							PortalID,username,ex),SecurityTraceSwitch.Sw.Info); 
				throw;
			}
		}

		#endregion Delete User

		#region password

		public bool CheckPassword( string username, string password, bool updateLastLoginActivityDate, bool failIfNotApproved)
		{
			string              salt;
			int                 passwordFormat;
			if (SecurityTraceSwitch.Sw.TraceVerbose)
				Trace.WriteLine( string.Format(CultureInfo.InvariantCulture,"[V]AddonNiceMembershipProvider CheckPassword BEG username: {0}, password: {1}.", username, password), SecurityTraceSwitch.Sw.Info);
			return CheckPassword(username, password, updateLastLoginActivityDate, failIfNotApproved, out salt, out passwordFormat);
		}

		private bool CheckPassword( string username, string password, bool updateLastLoginActivityDate, bool failIfNotApproved, out string salt, out int passwordFormat)
		{
			SqlConnectionHolder holder = null;
			string              passwdFromDB;
			int                 status;
			int                 failedPasswordAttemptCount;
			int                 failedPasswordAnswerAttemptCount;
			bool                isPasswordCorrect;
			bool                isApproved;
			DateTime            lastLoginDate, lastActivityDate;

			GetPasswordWithFormat(username, updateLastLoginActivityDate, out status, out passwdFromDB, out passwordFormat, out salt, out failedPasswordAttemptCount,
								  out failedPasswordAnswerAttemptCount, out isApproved, out lastLoginDate, out lastActivityDate);
			if (SecurityTraceSwitch.Sw.TraceVerbose)
				Trace.WriteLine( string.Format(CultureInfo.InvariantCulture,"[V]AddonNiceMembershipProvider CheckPassword afterGetPasswordWithFormat username: {0}, password: '{1}', status: {2}, passwdFromDB: '{3}', Salt: '{4}', isApproved: {5}.",
					new object[] { username, password, status, passwdFromDB,salt, isApproved }), SecurityTraceSwitch.Sw.Info);
			if (status != 0)
				return false;
			if (!isApproved && failIfNotApproved)
				return false;

			string encodedPasswd = EncodePassword( password, passwordFormat, salt );
			if (SecurityTraceSwitch.Sw.TraceVerbose)
				Trace.WriteLine( string.Format(CultureInfo.InvariantCulture,"[V]AddonNiceMembershipProvider CheckPassword username: {0}, password: {1}, encodedPasswd: '{2}', passwdFromDB: '{3}'.",
					new object[] { username, password, encodedPasswd, passwdFromDB}), SecurityTraceSwitch.Sw.Info);

			isPasswordCorrect = passwdFromDB.Equals( encodedPasswd );

			if( isPasswordCorrect && failedPasswordAttemptCount == 0 && failedPasswordAnswerAttemptCount == 0 )
				return true;

			if (SecurityTraceSwitch.Sw.TraceVerbose)
				Trace.WriteLine( string.Format(CultureInfo.InvariantCulture,"[V]AddonNiceMembershipProvider CheckPassword username: {0}, isPasswordCorrect: {1}, failedPasswordAttemptCount: '{2}', failedPasswordAnswerAttemptCount: '{3}'.",
					new object[] { username, isPasswordCorrect,failedPasswordAttemptCount,failedPasswordAnswerAttemptCount }), SecurityTraceSwitch.Sw.Info);
			try
			{
				try
				{
					holder                  =   SqlConnectionHelper.GetConnection(_sqlConnectionString, true);
					CheckSchemaVersion( holder.Connection );

					SqlCommand cmd          =   new SqlCommand( "dbo.AddonNice_Membership_UpdateUserInfo", holder.Connection );
					DateTime   dtNow        =   DateTime.UtcNow;
					cmd.CommandTimeout = CommandTimeout;
					cmd.CommandType = CommandType.StoredProcedure;
					cmd.Parameters.Add( CreateInputParam( "@ApplicationName", SqlDbType.NVarChar, ApplicationName ) );
					cmd.Parameters.Add( CreateInputParam( "@UserName", SqlDbType.NVarChar, username ) );
					cmd.Parameters.Add( CreateInputParam( "@IsPasswordCorrect", SqlDbType.Bit, isPasswordCorrect ) );
					cmd.Parameters.Add( CreateInputParam( "@UpdateLastLoginActivityDate", SqlDbType.Bit, updateLastLoginActivityDate ) );
					cmd.Parameters.Add( CreateInputParam( "@MaxInvalidPasswordAttempts", SqlDbType.Int, MaxInvalidPasswordAttempts ) );
					cmd.Parameters.Add( CreateInputParam( "@PasswordAttemptWindow", SqlDbType.Int, PasswordAttemptWindow ) );
					cmd.Parameters.Add( CreateInputParam( "@CurrentTimeUtc", SqlDbType.DateTime, dtNow));
					cmd.Parameters.Add( CreateInputParam( "@LastLoginDate", SqlDbType.DateTime, isPasswordCorrect ? dtNow : lastLoginDate));
					cmd.Parameters.Add( CreateInputParam( "@LastActivityDate", SqlDbType.DateTime, isPasswordCorrect ? dtNow : lastActivityDate));
					SqlParameter p          =   new SqlParameter("@ReturnValue", SqlDbType.Int);
					p.Direction             =   ParameterDirection.ReturnValue;
					cmd.Parameters.Add(p);

					cmd.ExecuteNonQuery();

					status                  =   ( ( p.Value != null ) ? ( ( int )p.Value ) : -1 );
				}
				finally
				{
					if( holder != null )
					{
						holder.Close();
						holder              =   null;
					}
				}
			}
			catch
			{
				throw;
			}

			return isPasswordCorrect;
		}

		private void GetPasswordWithFormat( string       username,
											bool         updateLastLoginActivityDate,
											out int      status,
											out string   password,
											out int      passwordFormat,
											out string   passwordSalt,
											out int      failedPasswordAttemptCount,
											out int      failedPasswordAnswerAttemptCount,
											out bool     isApproved,
											out DateTime lastLoginDate,
											out DateTime lastActivityDate)
		{
			try 
			{
				SqlConnectionHolder holder  =   null;
				SqlDataReader       reader  =   null;
				SqlParameter        p       =   null;

				try 
				{
					holder                  =   SqlConnectionHelper.GetConnection( _sqlConnectionString, true );
					CheckSchemaVersion( holder.Connection );

					SqlCommand    cmd       =   new SqlCommand( "dbo.AddonNice_Membership_GetPasswordWithFormat", holder.Connection );

					cmd.CommandTimeout      =   CommandTimeout;
					cmd.CommandType         =   CommandType.StoredProcedure;
					cmd.Parameters.Add(CreateInputParam("@ApplicationName", SqlDbType.NVarChar, ApplicationName ) );
					cmd.Parameters.Add(CreateInputParam("@UserName", SqlDbType.NVarChar, username ) );
					cmd.Parameters.Add(CreateInputParam("@UpdateLastLoginActivityDate", SqlDbType.Bit, updateLastLoginActivityDate));
					cmd.Parameters.Add(CreateInputParam("@CurrentTimeUtc", SqlDbType.DateTime, DateTime.UtcNow));

					p                       =   new SqlParameter("@ReturnValue", SqlDbType.Int );
					p.Direction             =   ParameterDirection.ReturnValue;
					cmd.Parameters.Add(p);

					reader                  =   cmd.ExecuteReader( CommandBehavior.SingleRow );

					status                  =   -1;

					if (reader.Read())
					{
						password            =   reader.GetString( 0 );
						passwordFormat      =   reader.GetInt32( 1 );
						passwordSalt        =   reader.GetString( 2 );
						failedPasswordAttemptCount = reader.GetInt32( 3 );
						failedPasswordAnswerAttemptCount = reader.GetInt32( 4 );
						isApproved          =   reader.GetBoolean(5);
						lastLoginDate       =   reader.GetDateTime(6);
						lastActivityDate    =   reader.GetDateTime(7);
					}
					else
					{
						password            =   null;
						passwordFormat      =   0;
						passwordSalt        =   null;
						failedPasswordAttemptCount = 0;
						failedPasswordAnswerAttemptCount = 0;
						isApproved          =   false;
						lastLoginDate       =   DateTime.UtcNow;
						lastActivityDate    =   DateTime.UtcNow;
					}
				}
				finally
				{
					if( reader != null )
					{
						reader.Close();
						reader              =    null;
						status              =   ( ( p.Value != null ) ? ( ( int )p.Value ) : -1 );
					}

					if( holder != null )
					{
						holder.Close();
						holder              =   null;
					}
				}
			} 
			catch
			{
				throw;
			}

		}

		private int GetPwdFormatAndSalt(string UserName,out int passwordFormat, out string salt)
		{
				string              passwdFromDB;
				int                 status;
				int                 failedPasswordAttemptCount;
				int                 failedPasswordAnswerAttemptCount;
				bool                isApproved;
				DateTime            lastLoginDate, lastActivityDate;

				GetPasswordWithFormat(UserName, false, out status, out passwdFromDB, out passwordFormat, out salt, out failedPasswordAttemptCount,
									  out failedPasswordAnswerAttemptCount, out isApproved, out lastLoginDate, out lastActivityDate);
			return status;
		}

		private string GetPasswordFromDB( string username,string passwordAnswer,bool requiresQuestionAndAnswer,out int passwordFormat,out int status )
		{
			try 
			{
				SqlConnectionHolder holder  =   null;
				SqlDataReader       reader  =   null;
				SqlParameter        p       =   null;

				try 
				{
					holder                  =   SqlConnectionHelper.GetConnection( _sqlConnectionString, true );
					CheckSchemaVersion( holder.Connection );

					SqlCommand cmd          =   new SqlCommand( "dbo.AddonNice_Membership_GetPassword", holder.Connection );

					cmd.CommandTimeout      =   CommandTimeout;
					cmd.CommandType         =   CommandType.StoredProcedure;
					cmd.Parameters.Add( CreateInputParam( "@ApplicationName", SqlDbType.NVarChar, ApplicationName ) );
					cmd.Parameters.Add( CreateInputParam( "@UserName", SqlDbType.NVarChar, username ) );
					cmd.Parameters.Add( CreateInputParam( "@MaxInvalidPasswordAttempts", SqlDbType.Int, MaxInvalidPasswordAttempts ) );
					cmd.Parameters.Add( CreateInputParam( "@PasswordAttemptWindow", SqlDbType.Int, PasswordAttemptWindow ) );
					cmd.Parameters.Add(CreateInputParam("@CurrentTimeUtc", SqlDbType.DateTime, DateTime.UtcNow));

					if ( requiresQuestionAndAnswer )
					{
						cmd.Parameters.Add( CreateInputParam( "@PasswordAnswer", SqlDbType.NVarChar, passwordAnswer ) );
					}

					p                       =   new SqlParameter( "@ReturnValue", SqlDbType.Int );
					p.Direction             =   ParameterDirection.ReturnValue;
					cmd.Parameters.Add(p);

					reader                  =   cmd.ExecuteReader( CommandBehavior.SingleRow );

					string password         =   null;

					status                  =   -1;

					if ( reader.Read() )
					{
						password            =   reader.GetString( 0 );
						passwordFormat      =   reader.GetInt32( 1 );
					}
					else
					{
						password            =   null;
						passwordFormat      =   0;
					}

					return password;
				}
				finally
				{
					if( reader != null )
					{
						reader.Close();
						reader              =   null;

						status              =   ( ( p.Value != null ) ? ( ( int )p.Value ) : -1 );
					}

					if( holder != null )
					{
						holder.Close();
						holder              =   null;
					}
				}
			}
			catch
			{
				throw;
			}

		}

		private string GetEncodedPasswordAnswer(string username, string passwordAnswer)
		{
			if( passwordAnswer != null )
			{
				passwordAnswer = passwordAnswer.Trim();
			}
			if (string.IsNullOrEmpty(passwordAnswer))
				return passwordAnswer;
			int status, passwordFormat, failedPasswordAttemptCount, failedPasswordAnswerAttemptCount;
			string password, passwordSalt;
			bool isApproved;
			DateTime lastLoginDate, lastActivityDate;
			GetPasswordWithFormat(username, false, out status, out password, out passwordFormat, out passwordSalt,
								  out failedPasswordAttemptCount, out failedPasswordAnswerAttemptCount, out isApproved, out lastLoginDate, out lastActivityDate);
			if (status == 0)
				return EncodePassword(passwordAnswer.ToLower(CultureInfo.InvariantCulture), passwordFormat, passwordSalt);
			else
				throw new ProviderException(GetExceptionText(status));
		}

		public virtual string GeneratePassword()
		{
			return Membership.GeneratePassword(
					  MinRequiredPasswordLength < PASSWORD_SIZE ? PASSWORD_SIZE : MinRequiredPasswordLength,
					  MinRequiredNonAlphanumericCharacters );
		}

		#endregion password

		#region Utilities

		private void CheckSchemaVersion( SqlConnection connection )
		{
			string[] features = { "AddonNice", "AddonNiceMembership" };
			string   version  = "1";

			SecUtility.CheckSchemaVersion( this,connection,features,version,ref _SchemaVersionCheck );
		}

		private SqlParameter CreateInputParam( string paramName,SqlDbType dbType,object objValue )
		{
			SqlParameter param      =   new SqlParameter( paramName, dbType );
			if( objValue == null )
			{
				param.IsNullable    =   true;
				param.Value         =   DBNull.Value;
			}
			else
			{
				param.Value         =   objValue;
			}

			return param;
		}

		private SqlParameter CreateInputParamSz( string paramName,SqlDbType dbType,object objValue,int sz )
		{
			SqlParameter param      =   new SqlParameter( paramName, dbType,sz );

			if( objValue == null )
			{
				param.IsNullable    =   true;
				param.Value         =   DBNull.Value;
			}
			else
			{
				param.Value         =   objValue;
			}

			return param;
		}

		private string GetNullableString(SqlDataReader reader, int col)
		{
			if( reader.IsDBNull( col ) == false )
				return reader.GetString( col );
			return null;
		}

		private string GetExceptionText(int status) 
		{
			string key;
			switch (status)
			{
			case 0:
				return String.Empty;
			case 1:
				key = SR.Membership_UserNotFound;
				break;
			case 2:
				key = SR.Membership_WrongPassword;
				break;
			case 3:
				key = SR.Membership_WrongAnswer;
				break;
			case 4:
				key = SR.Membership_InvalidPassword;
				break;
			case 5:
				key = SR.Membership_InvalidQuestion;
				break;
			case 6:
				key = SR.Membership_InvalidAnswer;
				break;
			case 7:
				key = SR.Membership_InvalidEmail;
				break;
			case 99:
				key = SR.Membership_AccountLockOut;
				break;
			default:
				key = SR.Provider_Error;
				break;
			}
			return SR.GetString(key);
		}

		private bool IsStatusDueToBadPassword( int status )
		{
			return ( status >= 2 && status <= 6 || status == 99 );
		}

		private DateTime RoundToSeconds(DateTime dt)
		{
			return new DateTime(dt.Year, dt.Month, dt.Day, dt.Hour, dt.Minute, dt.Second);
		}
		
		internal string GenerateSalt()
		{
			byte[] buf = new byte[16];
			(new RNGCryptoServiceProvider()).GetBytes(buf);
			return Convert.ToBase64String(buf);
		}

		internal string _CrmSalt = string.Empty;
		internal string GetCrmSalt()
		{
			if (string.IsNullOrEmpty(_CrmSalt))
			{
				string crmSalt  = Config.CRMDefaultCryptSalt;
				byte[] buf      = Convert.FromBase64String(crmSalt);
				byte[] bAll     = new byte[16];
				Buffer.BlockCopy(buf, 0, bAll, 0, (buf.Length > 16) ? 16 : buf.Length);
				_CrmSalt        = Convert.ToBase64String(bAll);
				if (SecurityTraceSwitch.Sw.TraceVerbose)
					Trace.WriteLine( string.Format(CultureInfo.InvariantCulture,"[V]AddonNiceMembershipProvider GetCrmSalt Config.crmSalt: '{0}', buf.Length: '{1}', Result: '{2}'", 
						crmSalt, buf.Length,_CrmSalt), SecurityTraceSwitch.Sw.Info);
			}
			return _CrmSalt;
		}

		internal string EncodeCrmPassword(string pass)
		{
			byte[] bIn      =   Encoding.Unicode.GetBytes(pass);
			byte[] bSalt    =   Convert.FromBase64String(GetCrmSalt());
			byte[] bAll     =   new byte[bSalt.Length + bIn.Length];

			Buffer.BlockCopy(bSalt, 0, bAll, 0, bSalt.Length);
			Buffer.BlockCopy(bIn, 0, bAll, bSalt.Length, bIn.Length);
			byte[] bRet     =   EncryptPassword(bAll);
			string result   = Convert.ToBase64String(bRet);
			if (SecurityTraceSwitch.Sw.TraceVerbose)
				Trace.WriteLine( string.Format(CultureInfo.InvariantCulture,"[V]AddonNiceMembershipProvider EncodeCrmPassword pass: '{0}', result: '{1}'",pass,result), SecurityTraceSwitch.Sw.Info);
			return result;
		}

		internal string UnEncodeCrmPassword(string pass)
		{
			byte[] bIn      =   Convert.FromBase64String(pass);
			byte[] bRet     =   DecryptPassword(bIn);
			if (bRet == null)
				return null;
			string result   =   Encoding.Unicode.GetString(bRet, 16, bRet.Length - 16);
			if (SecurityTraceSwitch.Sw.TraceVerbose)
				Trace.WriteLine( string.Format(CultureInfo.InvariantCulture,"[V]AddonNiceMembershipProvider EncodeCrmPassword pass: '{0}', result: '{1}'", pass, result), SecurityTraceSwitch.Sw.Info);
			return result;
		}

		internal string EncodePassword(string pass, int passwordFormat, string salt)
		{
			if (passwordFormat == 0) // MembershipPasswordFormat.Clear
				return pass;

			byte[] bIn      =   Encoding.Unicode.GetBytes(pass);
			byte[] bSalt    =   Convert.FromBase64String(salt);
			byte[] bAll     =   new byte[bSalt.Length + bIn.Length];
			byte[] bRet     =   null;

			Buffer.BlockCopy(bSalt, 0, bAll, 0, bSalt.Length);
			Buffer.BlockCopy(bIn, 0, bAll, bSalt.Length, bIn.Length);
			if (passwordFormat == 1)
			{ // MembershipPasswordFormat.Hashed
				HashAlgorithm s = HashAlgorithm.Create( Membership.HashAlgorithmType );
				bRet = s.ComputeHash(bAll);
			} else
			{
				bRet = EncryptPassword( bAll );
			}

			return Convert.ToBase64String(bRet);
		}

		internal string UnEncodePassword(string pass, int passwordFormat)
		{
			switch (passwordFormat)
			{
				case 0: // MembershipPasswordFormat.Clear:
					return pass;
				case 1: // MembershipPasswordFormat.Hashed:
					throw new ProviderException(SR.GetString(SR.Provider_can_not_decode_hashed_password));
				default:
					byte[] bIn  = Convert.FromBase64String(pass);
					byte[] bRet = DecryptPassword( bIn );
					if (bRet == null)
						return null;
					return Encoding.Unicode.GetString(bRet, 16, bRet.Length - 16);
			}
		}
	
	 #endregion Utilities
	}
}
